From 26fb294ca163df075c2bcce410eff0fec28cf342 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Thu, 9 Nov 2017 09:18:37 -0600
Subject: [PATCH 001/227] Update README.md

---
 README.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/README.md b/README.md
index 85e8992f80..46d6118fe6 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,10 @@
 
 A framework for building [json:api](http://jsonapi.org/) compliant web APIs. The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination. You just need to focus on defining the resources and implementing your custom business logic. This library has been designed around dependency injection making extensibility incredibly easy.
 
+## Examples
+
+See the [examples](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples) directory for up-to-date sample applications. There is also a [Todo List App](https://github.com/json-api-dotnet/TodoListExample) that includes a JADNC API and an EmberJs client.
+
 ## Installation And Usage
 
 See [the documentation](https://json-api-dotnet.github.io/JsonApiDotNetCore/) for detailed usage. 

From 8a6b6bdd69aacbf4d0a650d8cd5cc08369d5cf60 Mon Sep 17 00:00:00 2001
From: David Perfors <dnperfors@gmail.com>
Date: Sat, 11 Nov 2017 17:52:34 +0100
Subject: [PATCH 002/227] feat(JsonApiOptions): Add SerializerSettings to
 JsonApiOptions

* Add SerializerSettings to JsonApiOptions

* Fixed spacing, and added obsolete attribute to JsonContractResolver

* Correctly fix spacing.
---
 .../Configuration/JsonApiOptions.cs           | 15 +++++++-
 .../Serialization/JsonApiDeSerializer.cs      |  9 +----
 .../Serialization/JsonApiSerializer.cs        | 13 +++----
 .../Serialization/JsonApiDeSerializerTests.cs | 37 +++++++++----------
 .../Serialization/JsonApiSerializerTests.cs   | 10 ++---
 5 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index 3d169998a3..58d1a33376 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -3,6 +3,7 @@
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Serialization;
 using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
 using Newtonsoft.Json.Serialization;
 
 namespace JsonApiDotNetCore.Configuration
@@ -21,10 +22,20 @@ public class JsonApiOptions
         /// of the v1 spec. However, we have decided that this is a real
         /// requirement for users of this library and a gap in the specification.
         /// It will likely be removed when the spec is updated to support this
-        /// requirement. 
+        /// requirement.
         /// </summary>
         public bool AllowCustomQueryParameters { get; set; }
-        public IContractResolver JsonContractResolver { get; set; } = new DasherizedResolver();
+        [Obsolete("JsonContract resolver can now be set on SerializerSettings.")]
+        public IContractResolver JsonContractResolver
+        {
+            get => SerializerSettings.ContractResolver;
+            set => SerializerSettings.ContractResolver = value;
+        }
+        public JsonSerializerSettings SerializerSettings { get; } = new JsonSerializerSettings()
+        {
+            NullValueHandling = NullValueHandling.Ignore,
+            ContractResolver = new DasherizedResolver()
+        };
         internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder();
 
         public void BuildContextGraph<TContext>(Action<IContextGraphBuilder> builder)
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 608a23b66e..d8cbf245bf 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -135,12 +135,7 @@ private object ConvertAttrValue(object newValue, Type targetType)
 
         private object DeserializeComplexType(JContainer obj, Type targetType)
         {
-            var serializerSettings = new JsonSerializerSettings
-            {
-                ContractResolver = _jsonApiContext.Options.JsonContractResolver
-            };
-
-            return obj.ToObject(targetType, JsonSerializer.Create(serializerSettings));
+            return obj.ToObject(targetType, JsonSerializer.Create(_jsonApiContext.Options.SerializerSettings));
         }
 
         private object SetRelationships(
@@ -223,4 +218,4 @@ private object SetHasManyRelationship(object entity,
             return entity;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
index a7e14341b0..8e94835266 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
@@ -19,12 +19,12 @@ public JsonApiSerializer(
             IDocumentBuilder documentBuilder)
         {
             _jsonApiContext = jsonApiContext;
-            _documentBuilder = documentBuilder;            
+            _documentBuilder = documentBuilder;
         }
 
         public JsonApiSerializer(
             IJsonApiContext jsonApiContext,
-            IDocumentBuilder documentBuilder, 
+            IDocumentBuilder documentBuilder,
             ILoggerFactory loggerFactory)
         {
             _jsonApiContext = jsonApiContext;
@@ -43,7 +43,7 @@ public string Serialize(object entity)
             if (entity is IEnumerable<IIdentifiable>)
                 return SerializeDocuments(entity);
 
-            return SerializeDocument(entity);           
+            return SerializeDocument(entity);
         }
 
         private string GetNullDataResponse()
@@ -83,10 +83,7 @@ private string SerializeDocument(object entity)
 
         private string _serialize(object obj)
         {
-            return JsonConvert.SerializeObject(obj, new JsonSerializerSettings {
-                NullValueHandling = NullValueHandling.Ignore,
-                ContractResolver = _jsonApiContext.Options.JsonContractResolver
-            });
+            return JsonConvert.SerializeObject(obj, _jsonApiContext.Options.SerializerSettings);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index 53edc9faad..3e54c7b393 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -26,10 +26,10 @@ public void Can_Deserialize_Complex_Types()
             jsonApiContextMock.SetupAllProperties();
             jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
             jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
-            jsonApiContextMock.Setup(m => m.Options).Returns(new JsonApiOptions
-            {
-                JsonContractResolver = new CamelCasePropertyNamesContractResolver()
-            });
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
             var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
 
@@ -69,10 +69,9 @@ public void Can_Deserialize_Complex_List_Types()
             jsonApiContextMock.SetupAllProperties();
             jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
             jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
-            jsonApiContextMock.Setup(m => m.Options).Returns(new JsonApiOptions
-            {
-                JsonContractResolver = new CamelCasePropertyNamesContractResolver()
-            });
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
             var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
 
@@ -116,10 +115,9 @@ public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs()
             jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
             jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
 
-            jsonApiContextMock.Setup(m => m.Options).Returns(new JsonApiOptions
-            {
-                JsonContractResolver = new DasherizedResolver() // <---
-            });
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiOptions.SerializerSettings.ContractResolver = new DasherizedResolver(); // <--
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
             var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
 
@@ -162,10 +160,9 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
             jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
             jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(attributesToUpdate);
 
-            jsonApiContextMock.Setup(m => m.Options).Returns(new JsonApiOptions
-            {
-                JsonContractResolver = new DasherizedResolver()
-            });
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiOptions.SerializerSettings.ContractResolver = new DasherizedResolver();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
             var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
 
@@ -178,8 +175,8 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
                     Type = "test-resource",
                     Id = "1",
                     Attributes = new Dictionary<string, object> {
-                        { "complex-member", new Dictionary<string, string> { 
-                            { "compound-name",  "testName" } } 
+                        { "complex-member", new Dictionary<string, string> {
+                            { "compound-name",  "testName" } }
                         },
                         {  "immutable", "value"}
                     }
@@ -194,8 +191,8 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
             // assert
             Assert.NotNull(result.ComplexMember);
             Assert.Equal(1, attributesToUpdate.Count);
-            
-            foreach(var attr in attributesToUpdate)
+
+            foreach (var attr in attributesToUpdate)
                 Assert.False(attr.Key.IsImmutable);
         }
 
diff --git a/test/UnitTests/Serialization/JsonApiSerializerTests.cs b/test/UnitTests/Serialization/JsonApiSerializerTests.cs
index e671f3fc0c..3630cd6452 100644
--- a/test/UnitTests/Serialization/JsonApiSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiSerializerTests.cs
@@ -26,9 +26,7 @@ public void Can_Serialize_Complex_Types()
             var jsonApiContextMock = new Mock<IJsonApiContext>();
             jsonApiContextMock.SetupAllProperties();
             jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
-            jsonApiContextMock.Setup(m => m.Options).Returns(new JsonApiOptions {
-                JsonContractResolver = new DasherizedResolver()
-            });
+            jsonApiContextMock.Setup(m => m.Options).Returns(new JsonApiOptions());
             jsonApiContextMock.Setup(m => m.RequestEntity)
                 .Returns(contextGraph.GetContextEntity("test-resource"));
             jsonApiContextMock.Setup(m => m.MetaBuilder).Returns(new MetaBuilder());
@@ -36,8 +34,10 @@ public void Can_Serialize_Complex_Types()
 
             var documentBuilder = new DocumentBuilder(jsonApiContextMock.Object);
             var serializer = new JsonApiSerializer(jsonApiContextMock.Object, documentBuilder);
-            var resource = new TestResource {
-                ComplexMember = new ComplexType {
+            var resource = new TestResource
+            {
+                ComplexMember = new ComplexType
+                {
                     CompoundName = "testname"
                 }
             };

From e6e4cce270cf071f22a5b4d02f76ff0605bac653 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Sun, 12 Nov 2017 20:32:45 -0600
Subject: [PATCH 003/227] refactor(query-set): move logic into IQueryParser to
 improve extensibility

* chore(csproj): bump package version

* refactor(query-set): move logic into IQueryParser to improve extensibility

closes #186
---
 .../Configuration/JsonApiOptions.cs           |  12 +-
 .../IServiceCollectionExtensions.cs           |   2 +
 .../Internal/Query/QuerySet.cs                | 180 ----------------
 .../JsonApiDotNetCore.csproj                  |   2 +-
 .../Services/ControllerContext.cs             |  25 +++
 .../Services/JsonApiContext.cs                |  27 +--
 src/JsonApiDotNetCore/Services/QueryParser.cs | 198 ++++++++++++++++++
 test/UnitTests/Services/QueryAccessorTests.cs |  50 ++---
 .../QueryParser_Tests.cs}                     |  94 ++++-----
 9 files changed, 310 insertions(+), 280 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Services/ControllerContext.cs
 create mode 100644 src/JsonApiDotNetCore/Services/QueryParser.cs
 rename test/UnitTests/{Internal/QuerySet_Tests.cs => Services/QueryParser_Tests.cs} (72%)

diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index 58d1a33376..26e16b0741 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -16,15 +16,8 @@ public class JsonApiOptions
         public bool AllowClientGeneratedIds { get; set; }
         public IContextGraph ContextGraph { get; set; }
         public bool RelativeLinks { get; set; }
-
-        /// <summary>
-        /// This flag is experimental and could be perceived as a violation
-        /// of the v1 spec. However, we have decided that this is a real
-        /// requirement for users of this library and a gap in the specification.
-        /// It will likely be removed when the spec is updated to support this
-        /// requirement.
-        /// </summary>
         public bool AllowCustomQueryParameters { get; set; }
+
         [Obsolete("JsonContract resolver can now be set on SerializerSettings.")]
         public IContractResolver JsonContractResolver
         {
@@ -38,8 +31,7 @@ public IContractResolver JsonContractResolver
         };
         internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder();
 
-        public void BuildContextGraph<TContext>(Action<IContextGraphBuilder> builder)
-        where TContext : DbContext
+        public void BuildContextGraph<TContext>(Action<IContextGraphBuilder> builder) where TContext : DbContext
         {
             BuildContextGraph(builder);
 
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 3d2b14704a..afcc11ee8d 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -110,6 +110,8 @@ public static void AddJsonApiInternals(
             services.AddScoped<IGenericProcessorFactory, GenericProcessorFactory>();
             services.AddScoped(typeof(GenericProcessor<>));
             services.AddScoped<IQueryAccessor, QueryAccessor>();
+            services.AddScoped<IQueryParser, QueryParser>();
+            services.AddScoped<IControllerContext, Services.ControllerContext>();
         }
 
         public static void SerializeAsJsonApi(this MvcOptions options, JsonApiOptions jsonApiOptions)
diff --git a/src/JsonApiDotNetCore/Internal/Query/QuerySet.cs b/src/JsonApiDotNetCore/Internal/Query/QuerySet.cs
index 628e6187a3..88aac1e67b 100644
--- a/src/JsonApiDotNetCore/Internal/Query/QuerySet.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/QuerySet.cs
@@ -1,193 +1,13 @@
-using System;
 using System.Collections.Generic;
-using System.Linq;
-using JsonApiDotNetCore.Extensions;
-using JsonApiDotNetCore.Services;
-using Microsoft.AspNetCore.Http;
-using JsonApiDotNetCore.Models;
-using JsonApiDotNetCore.Controllers;
 
 namespace JsonApiDotNetCore.Internal.Query
 {
     public class QuerySet
     {
-        private readonly IJsonApiContext _jsonApiContext;
-
-        public QuerySet(
-            IJsonApiContext jsonApiContext,
-            IQueryCollection query)
-        {
-            _jsonApiContext = jsonApiContext;
-            BuildQuerySet(query);
-        }
-
         public List<FilterQuery> Filters { get; set; } = new List<FilterQuery>();
         public PageQuery PageQuery { get; set; } = new PageQuery();
         public List<SortQuery> SortParameters { get; set; } = new List<SortQuery>();
         public List<string> IncludedRelationships { get; set; } = new List<string>();
         public List<string> Fields { get; set; } = new List<string>();
-
-        private void BuildQuerySet(IQueryCollection query)
-        {
-            var disabledQueries = _jsonApiContext.GetControllerAttribute<DisableQueryAttribute>()?.QueryParams ?? QueryParams.None;
-
-            foreach (var pair in query)
-            {
-                if (pair.Key.StartsWith("filter"))
-                {
-                    if (disabledQueries.HasFlag(QueryParams.Filter) == false)
-                        Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
-                    continue;
-                }
-
-                if (pair.Key.StartsWith("sort"))
-                {
-                    if (disabledQueries.HasFlag(QueryParams.Sort) == false)
-                        SortParameters = ParseSortParameters(pair.Value);
-                    continue;
-                }
-
-                if (pair.Key.StartsWith("include"))
-                {
-                    if (disabledQueries.HasFlag(QueryParams.Include) == false)
-                        IncludedRelationships = ParseIncludedRelationships(pair.Value);
-                    continue;
-                }
-
-                if (pair.Key.StartsWith("page"))
-                {
-                    if (disabledQueries.HasFlag(QueryParams.Page) == false)
-                        PageQuery = ParsePageQuery(pair.Key, pair.Value);
-                    continue;
-                }
-
-                if (pair.Key.StartsWith("fields"))
-                {
-                    if (disabledQueries.HasFlag(QueryParams.Fields) == false)
-                        Fields = ParseFieldsQuery(pair.Key, pair.Value);
-                    continue;
-                }
-
-                if (_jsonApiContext.Options.AllowCustomQueryParameters == false)
-                    throw new JsonApiException(400, $"{pair} is not a valid query.");
-            }
-        }
-
-        private List<FilterQuery> ParseFilterQuery(string key, string value)
-        {
-            // expected input = filter[id]=1
-            // expected input = filter[id]=eq:1
-            var queries = new List<FilterQuery>();
-
-            var propertyName = key.Split('[', ']')[1].ToProperCase();
-
-            var values = value.Split(',');
-            foreach (var val in values)
-            {
-                (var operation, var filterValue) = ParseFilterOperation(val);
-                queries.Add(new FilterQuery(propertyName, filterValue, operation));
-            }
-
-            return queries;
-        }
-
-        private (string operation, string value) ParseFilterOperation(string value)
-        {
-            if (value.Length < 3)
-                return (string.Empty, value);
-
-            var operation = value.Split(':');
-
-            if (operation.Length == 1)
-                return (string.Empty, value);
-
-            // remove prefix from value
-            if (Enum.TryParse(operation[0], out FilterOperations op) == false)
-                return (string.Empty, value);
-
-            var prefix = operation[0];
-            value = string.Join(":", operation.Skip(1));
-
-            return (prefix, value);
-        }
-
-        private PageQuery ParsePageQuery(string key, string value)
-        {
-            // expected input = page[size]=10
-            //                  page[number]=1
-            PageQuery = PageQuery ?? new PageQuery();
-
-            var propertyName = key.Split('[', ']')[1];
-
-            if (propertyName == "size")
-                PageQuery.PageSize = Convert.ToInt32(value);
-            else if (propertyName == "number")
-                PageQuery.PageOffset = Convert.ToInt32(value);
-
-            return PageQuery;
-        }
-
-        // sort=id,name
-        // sort=-id
-        private List<SortQuery> ParseSortParameters(string value)
-        {
-            var sortParameters = new List<SortQuery>();
-            value.Split(',').ToList().ForEach(p =>
-            {
-                var direction = SortDirection.Ascending;
-                if (p[0] == '-')
-                {
-                    direction = SortDirection.Descending;
-                    p = p.Substring(1);
-                }
-
-                var attribute = GetAttribute(p.ToProperCase());
-
-                sortParameters.Add(new SortQuery(direction, attribute));
-            });
-
-            return sortParameters;
-        }
-
-        private List<string> ParseIncludedRelationships(string value)
-        {
-            if (value.Contains("."))
-                throw new JsonApiException(400, "Deeply nested relationships are not supported");
-
-            return value
-                .Split(',')
-                .ToList();
-        }
-
-        private List<string> ParseFieldsQuery(string key, string value)
-        {
-            // expected: fields[TYPE]=prop1,prop2
-            var typeName = key.Split('[', ']')[1];
-
-            var includedFields = new List<string> { "Id" };
-
-            if (typeName != _jsonApiContext.RequestEntity.EntityName)
-                return includedFields;
-
-            var fields = value.Split(',');
-            foreach (var field in fields)
-            {
-                var internalAttrName = _jsonApiContext.RequestEntity
-                    .Attributes
-                    .SingleOrDefault(attr => attr.PublicAttributeName == field)
-                    .InternalAttributeName;
-                includedFields.Add(internalAttrName);
-            }
-
-            return includedFields;
-        }
-
-        private AttrAttribute GetAttribute(string propertyName)
-        {
-            return _jsonApiContext.RequestEntity.Attributes
-                .FirstOrDefault(attr =>
-                    attr.InternalAttributeName.ToLower() == propertyName.ToLower()
-            );
-        }
     }
 }
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 03628876b9..c3c987f32a 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.1.8</VersionPrefix>
+    <VersionPrefix>2.1.9</VersionPrefix>
     <TargetFrameworks>netstandard1.6</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>
diff --git a/src/JsonApiDotNetCore/Services/ControllerContext.cs b/src/JsonApiDotNetCore/Services/ControllerContext.cs
new file mode 100644
index 0000000000..1984262b15
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/ControllerContext.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Reflection;
+using JsonApiDotNetCore.Internal;
+
+namespace JsonApiDotNetCore.Services
+{
+    public interface IControllerContext
+    {
+        Type ControllerType { get; set; }
+        ContextEntity RequestEntity { get; set; }
+        TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
+    }
+
+    public class ControllerContext : IControllerContext
+    {
+        public Type ControllerType { get; set; }
+        public ContextEntity RequestEntity { get; set; }
+
+        public TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute
+        {
+            var attribute = ControllerType.GetTypeInfo().GetCustomAttribute(typeof(TAttribute));
+            return attribute == null ? null : (TAttribute)attribute;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index e634938087..a93d76acdc 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -1,7 +1,6 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Reflection;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Data;
@@ -17,6 +16,8 @@ public class JsonApiContext : IJsonApiContext
     {
         private readonly IHttpContextAccessor _httpContextAccessor;
         private readonly IDbContextResolver _contextResolver;
+        private readonly IQueryParser _queryParser;
+        private readonly IControllerContext _controllerContext;
 
         public JsonApiContext(
             IDbContextResolver contextResolver,
@@ -24,7 +25,9 @@ public JsonApiContext(
             IHttpContextAccessor httpContextAccessor,
             JsonApiOptions options,
             IMetaBuilder metaBuilder,
-            IGenericProcessorFactory genericProcessorFactory)
+            IGenericProcessorFactory genericProcessorFactory,
+            IQueryParser queryParser,
+            IControllerContext controllerContext)
         {
             _contextResolver = contextResolver;
             ContextGraph = contextGraph;
@@ -32,11 +35,14 @@ public JsonApiContext(
             Options = options;
             MetaBuilder = metaBuilder;
             GenericProcessorFactory = genericProcessorFactory;
+            _queryParser = queryParser;
+            _controllerContext = controllerContext;
         }
 
         public JsonApiOptions Options { get; set; }
         public IContextGraph ContextGraph { get; set; }
-        public ContextEntity RequestEntity { get; set; }
+        [Obsolete("Use the proxied member IControllerContext.RequestEntity instead.")]
+        public ContextEntity RequestEntity { get => _controllerContext.RequestEntity; set => _controllerContext.RequestEntity = value; }
         public string BasePath { get; set; }
         public QuerySet QuerySet { get; set; }
         public bool IsRelationshipData { get; set; }
@@ -54,21 +60,20 @@ public IJsonApiContext ApplyContext<T>(object controller)
             if (controller == null)
                 throw new JsonApiException(500, $"Cannot ApplyContext from null controller for type {typeof(T)}");
 
-            ControllerType = controller.GetType();
+            _controllerContext.ControllerType = controller.GetType();
+            _controllerContext.RequestEntity = ContextGraph.GetContextEntity(typeof(T));
 
             var context = _httpContextAccessor.HttpContext;
             var path = context.Request.Path.Value.Split('/');
 
-            RequestEntity = ContextGraph.GetContextEntity(typeof(T));
-
             if (context.Request.Query.Any())
             {
-                QuerySet = new QuerySet(this, context.Request.Query);
+                QuerySet = _queryParser.Parse(context.Request.Query);
                 IncludedRelationships = QuerySet.IncludedRelationships;
             }
 
             var linkBuilder = new LinkBuilder(this);
-            BasePath = linkBuilder.GetBasePath(context, RequestEntity.EntityName);
+            BasePath = linkBuilder.GetBasePath(context, _controllerContext.RequestEntity.EntityName);
             PageManager = GetPageManager();
             IsRelationshipPath = path[path.Length - 2] == "relationships";
             return this;
@@ -91,10 +96,8 @@ private PageManager GetPageManager()
             };
         }
 
+        [Obsolete("Use the proxied method IControllerContext.GetControllerAttribute instead.")]
         public TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute
-        {
-            var attribute = ControllerType.GetTypeInfo().GetCustomAttribute(typeof(TAttribute));
-            return attribute == null ? null : (TAttribute)attribute;
-        }
+            => _controllerContext.GetControllerAttribute<TAttribute>();
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
new file mode 100644
index 0000000000..26c735e30c
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -0,0 +1,198 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Controllers;
+using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Internal.Query;
+using JsonApiDotNetCore.Models;
+using Microsoft.AspNetCore.Http;
+
+namespace JsonApiDotNetCore.Services
+{
+    public interface IQueryParser
+    {
+        QuerySet Parse(IQueryCollection query);
+    }
+
+    public class QueryParser : IQueryParser
+    {
+        private readonly IControllerContext _controllerContext;
+        private readonly JsonApiOptions _options;
+
+        public QueryParser(
+            IControllerContext controllerContext,
+            JsonApiOptions options)
+        {
+            _controllerContext = controllerContext;
+            _options = options;
+        }
+
+        public QuerySet Parse(IQueryCollection query)
+        {
+            var querySet = new QuerySet();
+            var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>()?.QueryParams ?? QueryParams.None;
+
+            foreach (var pair in query)
+            {
+                if (pair.Key.StartsWith("filter"))
+                {
+                    if (disabledQueries.HasFlag(QueryParams.Filter) == false)
+                        querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
+                    continue;
+                }
+
+                if (pair.Key.StartsWith("sort"))
+                {
+                    if (disabledQueries.HasFlag(QueryParams.Sort) == false)
+                        querySet.SortParameters = ParseSortParameters(pair.Value);
+                    continue;
+                }
+
+                if (pair.Key.StartsWith("include"))
+                {
+                    if (disabledQueries.HasFlag(QueryParams.Include) == false)
+                        querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value);
+                    continue;
+                }
+
+                if (pair.Key.StartsWith("page"))
+                {
+                    if (disabledQueries.HasFlag(QueryParams.Page) == false)
+                        querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value);
+                    continue;
+                }
+
+                if (pair.Key.StartsWith("fields"))
+                {
+                    if (disabledQueries.HasFlag(QueryParams.Fields) == false)
+                        querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value);
+                    continue;
+                }
+
+                if (_options.AllowCustomQueryParameters == false)
+                    throw new JsonApiException(400, $"{pair} is not a valid query.");
+            }
+
+            return querySet;
+        }
+
+        private List<FilterQuery> ParseFilterQuery(string key, string value)
+        {
+            // expected input = filter[id]=1
+            // expected input = filter[id]=eq:1
+            var queries = new List<FilterQuery>();
+
+            var propertyName = key.Split('[', ']')[1].ToProperCase();
+
+            var values = value.Split(',');
+            foreach (var val in values)
+            {
+                (var operation, var filterValue) = ParseFilterOperation(val);
+                queries.Add(new FilterQuery(propertyName, filterValue, operation));
+            }
+
+            return queries;
+        }
+
+        private (string operation, string value) ParseFilterOperation(string value)
+        {
+            if (value.Length < 3)
+                return (string.Empty, value);
+
+            var operation = value.Split(':');
+
+            if (operation.Length == 1)
+                return (string.Empty, value);
+
+            // remove prefix from value
+            if (Enum.TryParse(operation[0], out FilterOperations op) == false)
+                return (string.Empty, value);
+
+            var prefix = operation[0];
+            value = string.Join(":", operation.Skip(1));
+
+            return (prefix, value);
+        }
+
+        private PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value)
+        {
+            // expected input = page[size]=10
+            //                  page[number]=1
+            pageQuery = pageQuery ?? new PageQuery();
+
+            var propertyName = key.Split('[', ']')[1];
+
+            if (propertyName == "size")
+                pageQuery.PageSize = Convert.ToInt32(value);
+            else if (propertyName == "number")
+                pageQuery.PageOffset = Convert.ToInt32(value);
+
+            return pageQuery;
+        }
+
+        // sort=id,name
+        // sort=-id
+        private List<SortQuery> ParseSortParameters(string value)
+        {
+            var sortParameters = new List<SortQuery>();
+            value.Split(',').ToList().ForEach(p =>
+            {
+                var direction = SortDirection.Ascending;
+                if (p[0] == '-')
+                {
+                    direction = SortDirection.Descending;
+                    p = p.Substring(1);
+                }
+
+                var attribute = GetAttribute(p.ToProperCase());
+
+                sortParameters.Add(new SortQuery(direction, attribute));
+            });
+
+            return sortParameters;
+        }
+
+        private List<string> ParseIncludedRelationships(string value)
+        {
+            if (value.Contains("."))
+                throw new JsonApiException(400, "Deeply nested relationships are not supported");
+
+            return value
+                .Split(',')
+                .ToList();
+        }
+
+        private List<string> ParseFieldsQuery(string key, string value)
+        {
+            // expected: fields[TYPE]=prop1,prop2
+            var typeName = key.Split('[', ']')[1];
+
+            var includedFields = new List<string> { "Id" };
+
+            if (typeName != _controllerContext.RequestEntity.EntityName)
+                return includedFields;
+
+            var fields = value.Split(',');
+            foreach (var field in fields)
+            {
+                var internalAttrName = _controllerContext.RequestEntity
+                    .Attributes
+                    .SingleOrDefault(attr => attr.PublicAttributeName == field)
+                    .InternalAttributeName;
+                includedFields.Add(internalAttrName);
+            }
+
+            return includedFields;
+        }
+
+        private AttrAttribute GetAttribute(string propertyName)
+            => _controllerContext
+                .RequestEntity
+                .Attributes
+                .FirstOrDefault(attr =>
+                    string.Equals(attr.InternalAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
+                );
+    }
+}
\ No newline at end of file
diff --git a/test/UnitTests/Services/QueryAccessorTests.cs b/test/UnitTests/Services/QueryAccessorTests.cs
index 45538fde66..aa8bc6ae7e 100644
--- a/test/UnitTests/Services/QueryAccessorTests.cs
+++ b/test/UnitTests/Services/QueryAccessorTests.cs
@@ -5,7 +5,6 @@
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Primitives;
 using Moq;
 using Xunit;
 
@@ -28,19 +27,16 @@ public QueryAccessorTests()
         public void Can_Get_Guid_QueryValue()
         {
             // arrange
-            const string key = "some-id";
-            var filterQuery = $"filter[{key}]";
+            const string key = "SomeId";
             var value = Guid.NewGuid();
-
-            var query = new Dictionary<string, StringValues> {
-                { filterQuery, value.ToString() }
+            var querySet = new QuerySet
+            {
+                Filters = new List<FilterQuery> {
+                    new FilterQuery(key, value.ToString(), "eq")
+                }
             };
 
-            _queryMock.Setup(q => q.GetEnumerator()).Returns(query.GetEnumerator());
-
-            var querySet = new QuerySet(_contextMock.Object, _queryMock.Object);
-            _contextMock.Setup(c => c.QuerySet)
-                .Returns(querySet);
+            _contextMock.Setup(c => c.QuerySet).Returns(querySet);
 
             var service = new QueryAccessor(_contextMock.Object, _loggerMock.Object);
 
@@ -56,19 +52,17 @@ public void Can_Get_Guid_QueryValue()
         public void GetRequired_Throws_If_Not_Present()
         {
             // arrange
-            const string key = "some-id";
-            var filterQuery = $"filter[{key}]";
+            const string key = "SomeId";
             var value = Guid.NewGuid();
 
-            var query = new Dictionary<string, StringValues> {
-                { filterQuery, value.ToString() }
+            var querySet = new QuerySet
+            {
+                Filters = new List<FilterQuery> {
+                    new FilterQuery(key, value.ToString(), "eq")
+                }
             };
 
-            _queryMock.Setup(q => q.GetEnumerator()).Returns(query.GetEnumerator());
-
-            var querySet = new QuerySet(_contextMock.Object, _queryMock.Object);
-            _contextMock.Setup(c => c.QuerySet)
-                .Returns(querySet);
+            _contextMock.Setup(c => c.QuerySet).Returns(querySet);
 
             var service = new QueryAccessor(_contextMock.Object, _loggerMock.Object);
 
@@ -83,19 +77,17 @@ public void GetRequired_Throws_If_Not_Present()
         public void GetRequired_Does_Not_Throw_If_Present()
         {
             // arrange
-            const string key = "some-id";
-            var filterQuery = $"filter[{key}]";
+            const string key = "SomeId";
             var value = Guid.NewGuid();
 
-            var query = new Dictionary<string, StringValues> {
-                { filterQuery, value.ToString() }
+            var querySet = new QuerySet
+            {
+                Filters = new List<FilterQuery> {
+                    new FilterQuery(key, value.ToString(), "eq")
+                }
             };
 
-            _queryMock.Setup(q => q.GetEnumerator()).Returns(query.GetEnumerator());
-
-            var querySet = new QuerySet(_contextMock.Object, _queryMock.Object);
-            _contextMock.Setup(c => c.QuerySet)
-                .Returns(querySet);
+            _contextMock.Setup(c => c.QuerySet).Returns(querySet);
 
             var service = new QueryAccessor(_contextMock.Object, _loggerMock.Object);
 
diff --git a/test/UnitTests/Internal/QuerySet_Tests.cs b/test/UnitTests/Services/QueryParser_Tests.cs
similarity index 72%
rename from test/UnitTests/Internal/QuerySet_Tests.cs
rename to test/UnitTests/Services/QueryParser_Tests.cs
index 2a433e63af..a64c5b3692 100644
--- a/test/UnitTests/Internal/QuerySet_Tests.cs
+++ b/test/UnitTests/Services/QueryParser_Tests.cs
@@ -1,25 +1,23 @@
-using System;
 using System.Collections.Generic;
 using System.Linq;
+using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Controllers;
-using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Primitives;
 using Moq;
 using Xunit;
 
-namespace UnitTests.Internal
+namespace UnitTests.Services
 {
-    public class QuerySet_Tests
+    public class QueryParser_Tests
     {
-        private readonly Mock<IJsonApiContext> _jsonApiContextMock;
+        private readonly Mock<IControllerContext> _controllerContextMock;
         private readonly Mock<IQueryCollection> _queryCollectionMock;
 
-        public QuerySet_Tests()
+        public QueryParser_Tests()
         {
-            _jsonApiContextMock = new Mock<IJsonApiContext>();
+            _controllerContextMock = new Mock<IControllerContext>();
             _queryCollectionMock = new Mock<IQueryCollection>();
         }
 
@@ -35,14 +33,14 @@ public void Can_Build_Filters()
                 .Setup(m => m.GetEnumerator())
                 .Returns(query.GetEnumerator());
 
-            _jsonApiContextMock
+            _controllerContextMock
                 .Setup(m => m.GetControllerAttribute<DisableQueryAttribute>())
                 .Returns(new DisableQueryAttribute(QueryParams.None));
 
-            // act -- ctor calls BuildQuerySet()
-            var querySet = new QuerySet(
-                _jsonApiContextMock.Object,
-                _queryCollectionMock.Object);
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
             Assert.Equal("value", querySet.Filters.Single(f => f.Key == "Key").Value);
@@ -61,14 +59,14 @@ public void Filters_Properly_Parses_DateTime_With_Operation()
                 .Setup(m => m.GetEnumerator())
                 .Returns(query.GetEnumerator());
 
-            _jsonApiContextMock
+            _controllerContextMock
                 .Setup(m => m.GetControllerAttribute<DisableQueryAttribute>())
                 .Returns(new DisableQueryAttribute(QueryParams.None));
 
-            // act -- ctor calls BuildQuerySet()
-            var querySet = new QuerySet(
-                _jsonApiContextMock.Object,
-                _queryCollectionMock.Object);
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
             Assert.Equal(dt, querySet.Filters.Single(f => f.Key == "Key").Value);
@@ -88,14 +86,14 @@ public void Filters_Properly_Parses_DateTime_Without_Operation()
                 .Setup(m => m.GetEnumerator())
                 .Returns(query.GetEnumerator());
 
-            _jsonApiContextMock
+            _controllerContextMock
                 .Setup(m => m.GetControllerAttribute<DisableQueryAttribute>())
                 .Returns(new DisableQueryAttribute(QueryParams.None));
 
-            // act -- ctor calls BuildQuerySet()
-            var querySet = new QuerySet(
-                _jsonApiContextMock.Object,
-                _queryCollectionMock.Object);
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
             Assert.Equal(dt, querySet.Filters.Single(f => f.Key == "Key").Value);
@@ -114,14 +112,14 @@ public void Can_Disable_Filters()
                 .Setup(m => m.GetEnumerator())
                 .Returns(query.GetEnumerator());
 
-            _jsonApiContextMock
+            _controllerContextMock
                 .Setup(m => m.GetControllerAttribute<DisableQueryAttribute>())
                 .Returns(new DisableQueryAttribute(QueryParams.Filter));
 
-            // act -- ctor calls BuildQuerySet()
-            var querySet = new QuerySet(
-                _jsonApiContextMock.Object,
-                _queryCollectionMock.Object);
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
             Assert.Empty(querySet.Filters);
@@ -139,14 +137,14 @@ public void Can_Disable_Sort()
                 .Setup(m => m.GetEnumerator())
                 .Returns(query.GetEnumerator());
 
-            _jsonApiContextMock
+            _controllerContextMock
                 .Setup(m => m.GetControllerAttribute<DisableQueryAttribute>())
                 .Returns(new DisableQueryAttribute(QueryParams.Sort));
 
-            // act -- ctor calls BuildQuerySet()
-            var querySet = new QuerySet(
-                _jsonApiContextMock.Object,
-                _queryCollectionMock.Object);
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
             Assert.Empty(querySet.SortParameters);
@@ -164,14 +162,14 @@ public void Can_Disable_Include()
                 .Setup(m => m.GetEnumerator())
                 .Returns(query.GetEnumerator());
 
-            _jsonApiContextMock
+            _controllerContextMock
                 .Setup(m => m.GetControllerAttribute<DisableQueryAttribute>())
                 .Returns(new DisableQueryAttribute(QueryParams.Include));
 
-            // act -- ctor calls BuildQuerySet()
-            var querySet = new QuerySet(
-                _jsonApiContextMock.Object,
-                _queryCollectionMock.Object);
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
             Assert.Empty(querySet.IncludedRelationships);
@@ -189,14 +187,14 @@ public void Can_Disable_Page()
                 .Setup(m => m.GetEnumerator())
                 .Returns(query.GetEnumerator());
 
-            _jsonApiContextMock
+            _controllerContextMock
                 .Setup(m => m.GetControllerAttribute<DisableQueryAttribute>())
                 .Returns(new DisableQueryAttribute(QueryParams.Page));
 
-            // act -- ctor calls BuildQuerySet()
-            var querySet = new QuerySet(
-                _jsonApiContextMock.Object,
-                _queryCollectionMock.Object);
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
             Assert.Equal(0, querySet.PageQuery.PageSize);
@@ -214,14 +212,14 @@ public void Can_Disable_Fields()
                 .Setup(m => m.GetEnumerator())
                 .Returns(query.GetEnumerator());
 
-            _jsonApiContextMock
+            _controllerContextMock
                 .Setup(m => m.GetControllerAttribute<DisableQueryAttribute>())
                 .Returns(new DisableQueryAttribute(QueryParams.Fields));
 
-            // act -- ctor calls BuildQuerySet()
-            var querySet = new QuerySet(
-                _jsonApiContextMock.Object,
-                _queryCollectionMock.Object);
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
             Assert.Empty(querySet.Fields);

From fc161d2708fbfcd6256c74b218c99c5a28506700 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 9 Aug 2017 22:16:01 -0500
Subject: [PATCH 004/227] feat(models): initial operation models

---
 .../Controllers/QueryParams.cs                |  2 -
 .../Models/Operations/Operation.cs            | 53 +++++++++++++++++++
 .../Models/Operations/OperationCode.cs        | 10 ++++
 .../Models/Operations/ResourceReference.cs    | 16 ++++++
 4 files changed, 79 insertions(+), 2 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Models/Operations/Operation.cs
 create mode 100644 src/JsonApiDotNetCore/Models/Operations/OperationCode.cs
 create mode 100644 src/JsonApiDotNetCore/Models/Operations/ResourceReference.cs

diff --git a/src/JsonApiDotNetCore/Controllers/QueryParams.cs b/src/JsonApiDotNetCore/Controllers/QueryParams.cs
index 7e59f976c5..4c963098ad 100644
--- a/src/JsonApiDotNetCore/Controllers/QueryParams.cs
+++ b/src/JsonApiDotNetCore/Controllers/QueryParams.cs
@@ -1,5 +1,3 @@
-using System;
-
 namespace JsonApiDotNetCore.Controllers
 {
     public enum QueryParams
diff --git a/src/JsonApiDotNetCore/Models/Operations/Operation.cs b/src/JsonApiDotNetCore/Models/Operations/Operation.cs
new file mode 100644
index 0000000000..533af2e109
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/Operations/Operation.cs
@@ -0,0 +1,53 @@
+using System.Collections;
+using System.Collections.Generic;
+using JsonApiDotNetCore.Controllers;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace JsonApiDotNetCore.Models.Operations
+{
+    public class Operation : DocumentBase
+    {
+        [JsonProperty("op")]
+        public OperationCode Op { get; set; }
+
+        [JsonProperty("ref")]
+        public ResourceReference Ref { get; set; }
+
+        [JsonProperty("params")]
+        public QueryParams Params { get; set; }
+
+        [JsonProperty("data")]
+        public object Data
+        {
+            get
+            {
+                if (DataIsList) return DataList;
+                return DataObject;
+            }
+            set => SetData(value);
+        }
+
+        private void SetData(object data)
+        {
+            if (data is JArray jArray) {
+                DataIsList = true;
+                DataList = jArray.ToObject<List<DocumentData>>();
+            }
+            else if (data is List<DocumentData> dataList) {
+                DataIsList = true;
+                DataList = dataList;
+            }
+            else if (data is JObject jObject) {
+                DataObject = jObject.ToObject<DocumentData>();
+            }
+            else if (data is DocumentData dataObject) {
+                DataObject = dataObject;
+            }
+        }
+
+        public bool DataIsList { get; private set; }
+        public List<DocumentData> DataList { get; private set; }
+        public DocumentData DataObject { get; private set; }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs b/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs
new file mode 100644
index 0000000000..ffe3310985
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs
@@ -0,0 +1,10 @@
+namespace JsonApiDotNetCore.Models.Operations
+{
+    public enum OperationCode
+    {
+        get = 1,
+        add = 2,
+        replace = 3,
+        remove = 4
+    }
+}
diff --git a/src/JsonApiDotNetCore/Models/Operations/ResourceReference.cs b/src/JsonApiDotNetCore/Models/Operations/ResourceReference.cs
new file mode 100644
index 0000000000..a8caa7ca05
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/Operations/ResourceReference.cs
@@ -0,0 +1,16 @@
+using Newtonsoft.Json;
+
+namespace JsonApiDotNetCore.Models.Operations
+{
+    public class ResourceReference
+    {
+        [JsonProperty("type")]
+        public object Type { get; set; }
+
+        [JsonProperty("id")]
+        public object Id { get; set; }
+        
+        [JsonProperty("relationship")]
+        public string Relationship { get; set; }
+    }
+}

From c504ef17496e0fa3de1b6f7f8b032cf7b2cc53a5 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 9 Aug 2017 22:16:33 -0500
Subject: [PATCH 005/227] feat(pointers): first pass at OperationsPointer

---
 .../JsonApiDotNetCore.csproj                  |  3 +-
 .../Models/Pointers/OperationsPointer.cs      | 84 +++++++++++++++++++
 .../Models/Pointers/Pointer.cs                | 22 +++++
 3 files changed, 108 insertions(+), 1 deletion(-)
 create mode 100644 src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
 create mode 100644 src/JsonApiDotNetCore/Models/Pointers/Pointer.cs

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index c3c987f32a..a67648a417 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -19,6 +19,7 @@
     <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
     <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
+    <PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.2" />
     <PackageReference Include="System.ValueTuple" Version="4.3.1" />
   </ItemGroup>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
new file mode 100644
index 0000000000..61b9b9b166
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models.Operations;
+
+namespace JsonApiDotNetCore.Models.Pointers
+{
+    public class OperationsPointer : Pointer
+    {
+        /// <exception cref="System.ArgumentNullException"></exception>
+        /// <exception cref="System.ArgumentException"></exception>
+        /// <exception cref="System.InvalidOperationException"></exception>
+        /// <exception cref="JsonApiDotNetCore.Internal.JsonApiException"></exception>
+        public override object GetValue(object root)
+        {
+            if (root == null) throw new ArgumentNullException(nameof(root));
+            if (PointerAddress == null) throw new InvalidOperationException("Cannot get pointer value from null PointerAddress");
+            
+            if (root is List<Operation> operations) 
+                return GetValueFromRoot(operations);
+
+            throw new ArgumentException(nameof(root));
+        }
+
+        private object GetValueFromRoot(List<Operation> operations)
+        {
+            var pathSegments = PointerAddress.Split('/');
+
+            if(pathSegments.Length < 4)
+                throw BadRequestException("number of segments", pathSegments.Length);
+
+            if (pathSegments[0] != "operations")
+                throw BadRequestException("prefix", pathSegments[0]);
+
+            // /operations/{operationIndex} → operations = [...]
+            if(int.TryParse(pathSegments[1], out int operationIndex))
+                return GetValueFromOperation(operations[operationIndex], pathSegments);
+            else
+                throw BadRequestException("operation index", operationIndex);
+        }
+
+        private object GetValueFromOperation(Operation operation, string[] pathSegments)
+        {
+            var operationPropertyName = pathSegments[2];
+            if(operationPropertyName != "data") 
+                throw BadRequestException("operation property name", operationPropertyName);
+            
+            // /operations/0/data → data = {...}
+            if(operation.DataIsList ==  false)
+                return GetValueFromData(operation.DataObject, pathSegments, segementStartIndex: 3);
+
+            // /operations/0/data/{dataIndex} → data = [...]
+            if(int.TryParse(pathSegments[3], out int dataIndex)) {
+                if(operation.DataList.Count >= dataIndex - 1)
+                    return GetValueFromData(operation.DataList[dataIndex], pathSegments, segementStartIndex: 4);
+                throw BadRequestException("data index", dataIndex, "Pointer references an index in the data array that cannot be found at the specified position.");
+            }
+            else {
+                throw BadRequestException("data index", dataIndex, "Pointer segement should provide array index but could not be parsed to an integer.");
+            }
+        }
+
+        private object GetValueFromData(DocumentData data, string[] pathSegments, int segementStartIndex)
+        {
+            // /operations/0/data/{dataPropertyName}
+            if(pathSegments.Length <= segementStartIndex)
+                throw BadRequestException("length", pathSegments.Length, "Pointer does not contain enough segments to locate data property.");
+
+            var dataPropertyName = pathSegments[segementStartIndex];
+            switch(dataPropertyName)
+            {
+                case "id":
+                    return data.Id;
+                case "type":
+                    return data.Type;
+                default:
+                    throw BadRequestException("data property name", dataPropertyName, "Only 'id' and 'type' pointers are supported.");
+            }
+        }
+
+        private JsonApiException BadRequestException(string condition, object value, string extraDetail = null)
+            => new JsonApiException(400, $"Operations pointer has invalid {condition} '{value}' in pointer '{PointerAddress}'. {extraDetail}");
+    }
+}
diff --git a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs b/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
new file mode 100644
index 0000000000..ecb25f314c
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
@@ -0,0 +1,22 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Schema;
+
+namespace JsonApiDotNetCore.Models.Pointers
+{
+    public abstract class Pointer
+    {
+        private static JSchema JsonSchema { get; } = JSchema.Parse("{ 'pointer': {'type': 'string'} }");
+
+        /// <summary>
+        /// Location represented by the pointer
+        /// </summary>
+        /// <example>/operations/0/data/id</example>
+        [JsonProperty("pointer")]
+        public string PointerAddress { get; set; }
+
+        /// <summary>
+        /// Get the value located at the PointerAddress in the supplied object
+        /// </summary>
+        public abstract object GetValue(object root);
+    }
+}

From be26e89849b6319a4ab3d3209053dfe9689db089 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 10 Aug 2017 22:56:48 -0500
Subject: [PATCH 006/227] feat(pointers): wrap up OperationsPointers and tests

---
 .../Builders/DocumentBuilder.cs               |  10 +-
 .../Models/Pointers/OperationsPointer.cs      |   2 +-
 .../Models/RelationshipData.cs                |  12 +-
 .../Serialization/JsonApiDeSerializer.cs      |   6 +-
 .../Models/Pointers/OperationsPointerTests.cs | 145 ++++++++++++++++++
 5 files changed, 160 insertions(+), 15 deletions(-)
 create mode 100644 test/UnitTests/Models/Pointers/OperationsPointerTests.cs

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index d8d38390d8..ae102111c3 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -227,29 +227,29 @@ private bool RelationshipIsIncluded(string relationshipName)
                 _jsonApiContext.IncludedRelationships.Contains(relationshipName);
         }
 
-        private List<Dictionary<string, string>> GetRelationships(IEnumerable<object> entities)
+        private List<Dictionary<string, object>> GetRelationships(IEnumerable<object> entities)
         {
             var objType = entities.GetType().GenericTypeArguments[0];
 
             var typeName = _jsonApiContext.ContextGraph.GetContextEntity(objType);
 
-            var relationships = new List<Dictionary<string, string>>();
+            var relationships = new List<Dictionary<string, object>>();
             foreach (var entity in entities)
             {
-                relationships.Add(new Dictionary<string, string> {
+                relationships.Add(new Dictionary<string, object> {
                     {"type", typeName.EntityName },
                     {"id", ((IIdentifiable)entity).StringId }
                 });
             }
             return relationships;
         }
-        private Dictionary<string, string> GetRelationship(object entity)
+        private Dictionary<string, object> GetRelationship(object entity)
         {
             var objType = entity.GetType();
 
             var typeName = _jsonApiContext.ContextGraph.GetContextEntity(objType);
 
-            return new Dictionary<string, string> {
+            return new Dictionary<string, object> {
                     {"type", typeName.EntityName },
                     {"id", ((IIdentifiable)entity).StringId }
                 };
diff --git a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
index 61b9b9b166..5c5d852b25 100644
--- a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
+++ b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
@@ -24,7 +24,7 @@ public override object GetValue(object root)
 
         private object GetValueFromRoot(List<Operation> operations)
         {
-            var pathSegments = PointerAddress.Split('/');
+            var pathSegments = PointerAddress.Split(new [] { '/' } , StringSplitOptions.RemoveEmptyEntries);
 
             if(pathSegments.Length < 4)
                 throw BadRequestException("number of segments", pathSegments.Length);
diff --git a/src/JsonApiDotNetCore/Models/RelationshipData.cs b/src/JsonApiDotNetCore/Models/RelationshipData.cs
index 21efa7409c..f74651318e 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipData.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipData.cs
@@ -20,20 +20,20 @@ public object ExposedData {
             set {
                 if(value is IEnumerable)
                     if(value is JObject jObject)
-                        SingleData = jObject.ToObject<Dictionary<string, string>>();   
+                        SingleData = jObject.ToObject<Dictionary<string, object>>();   
                     else if(value is JArray jArray)
-                        ManyData = jArray.ToObject<List<Dictionary<string, string>>>();
+                        ManyData = jArray.ToObject<List<Dictionary<string, object>>>();
                     else
-                        ManyData = (List<Dictionary<string, string>>)value;
+                        ManyData = (List<Dictionary<string, object>>)value;
                 else
-                    SingleData = (Dictionary<string, string>)value;
+                    SingleData = (Dictionary<string, object>)value;
             }
          }
 
         [JsonIgnore]
-        public List<Dictionary<string, string>> ManyData { get; set; }
+        public List<Dictionary<string, object>> ManyData { get; set; }
         
         [JsonIgnore]
-        public Dictionary<string, string> SingleData { get; set; }
+        public Dictionary<string, object> SingleData { get; set; }
     }
 }
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index d8cbf245bf..021adbe538 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -176,7 +176,7 @@ private object SetHasOneRelationship(object entity,
                 var relationshipAttr = _jsonApiContext.RequestEntity.Relationships
                         .SingleOrDefault(r => r.PublicRelationshipName == relationshipName);
 
-                var data = (Dictionary<string, string>)relationshipData.ExposedData;
+                var data = (Dictionary<string, object>)relationshipData.ExposedData;
 
                 if (data == null) return entity;
 
@@ -206,12 +206,12 @@ private object SetHasManyRelationship(object entity,
 
             if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
             {
-                var data = (List<Dictionary<string, string>>)relationshipData.ExposedData;
+                var data = (List<Dictionary<string, object>>)relationshipData.ExposedData;
 
                 if (data == null) return entity;
 
                 var genericProcessor = _genericProcessorFactory.GetProcessor(attr.Type);
-                var ids = relationshipData.ManyData.Select(r => r["id"]);
+                var ids = relationshipData.ManyData.Select(r => r["id"].ToString());
                 genericProcessor.SetRelationships(entity, attr, ids);
             }
 
diff --git a/test/UnitTests/Models/Pointers/OperationsPointerTests.cs b/test/UnitTests/Models/Pointers/OperationsPointerTests.cs
new file mode 100644
index 0000000000..4a82e1a164
--- /dev/null
+++ b/test/UnitTests/Models/Pointers/OperationsPointerTests.cs
@@ -0,0 +1,145 @@
+using System.Collections.Generic;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Models.Pointers;
+using Newtonsoft.Json;
+using Xunit;
+
+namespace UnitTests.Models.Pointers
+{
+    public class OperationsPointerTests
+    {
+        [Fact]
+        public void GetValue_Can_Get_Value_From_Data_Id()
+        {
+            // arrange
+            var json = @"[
+                {
+                    ""op"": ""add"",
+                    ""data"": {
+                        ""id"": ""1"",
+                        ""type"": ""authors"",
+                        ""attributes"": {
+                            ""name"": ""dgeb""
+                        }
+                    }
+                }]";
+            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
+            var pointerJson = @"{ ""pointer"": ""/operations/0/data/id"" }";
+            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
+            var value = pointer.GetValue(operations);
+            Assert.Equal("1", value.ToString());
+        }
+
+        [Fact]
+        public void GetValue_Can_Get_Value_From_Data_Type()
+        {
+            // arrange
+            var json = @"[
+                {
+                    ""op"": ""add"",
+                    ""data"": {
+                        ""id"": ""1"",
+                        ""type"": ""authors"",
+                        ""attributes"": {
+                            ""name"": ""dgeb""
+                        }
+                    }
+                }]";
+            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
+            var pointerJson = @"{ ""pointer"": ""/operations/0/data/type"" }";
+            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
+            var value = pointer.GetValue(operations);
+            Assert.Equal("authors", value.ToString());
+        }
+
+        [Fact]
+        public void GetValue_Can_Get_Value_From_ListData_Id()
+        {
+            // arrange
+            var json = @"[
+                {
+                    ""op"": ""get"",
+                    ""data"": [{
+                        ""id"": ""1"",
+                        ""type"": ""authors"",
+                        ""attributes"": {
+                            ""name"": ""dgeb""
+                        }
+                    }, {
+                        ""id"": ""2"",
+                        ""type"": ""authors"",
+                        ""attributes"": {
+                            ""name"": ""jaredcnance""
+                        }
+                    }]
+                }]";
+            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
+            var pointerJson = @"{ ""pointer"": ""/operations/0/data/1/id"" }";
+            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
+            var value = pointer.GetValue(operations);
+            Assert.Equal("2", value.ToString());
+        }
+
+        [Fact]
+        public void GetValue_Can_Get_Value_From_Second_Operations_Data_Id()
+        {
+            // arrange
+            var json = @"[
+                {
+                    ""op"": ""get"",
+                    ""data"": {
+                        ""id"": ""1"",
+                        ""type"": ""authors"",
+                        ""attributes"": {
+                            ""name"": ""dgeb""
+                        }
+                    }
+                },{
+                    ""op"": ""get"",
+                    ""data"": {
+                        ""id"": ""2"",
+                        ""type"": ""authors"",
+                        ""attributes"": {
+                            ""name"": ""jaredcnance""
+                        }
+                    }
+                }]";
+            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
+            var pointerJson = @"{ ""pointer"": ""/operations/1/data/id"" }";
+            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
+            var value = pointer.GetValue(operations);
+            Assert.Equal("2", value.ToString());
+        }
+
+        [Fact]
+        public void GetValue_Can_Get_Value_From_Second_Operations_Data_Type()
+        {
+            // arrange
+            var json = @"[
+                {
+                    ""op"": ""get"",
+                    ""data"": {
+                        ""id"": ""1"",
+                        ""type"": ""authors"",
+                        ""attributes"": {
+                            ""name"": ""dgeb""
+                        }
+                    }
+                },{
+                    ""op"": ""get"",
+                    ""data"": {
+                        ""id"": ""1"",
+                        ""type"": ""articles"",
+                        ""attributes"": {
+                            ""name"": ""JSON API paints my bikeshed!""
+                        }
+                    }
+                }]";
+            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
+            var pointerJson = @"{ ""pointer"": ""/operations/1/data/type"" }";
+            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
+            var value = pointer.GetValue(operations);
+            Assert.Equal("articles", value.ToString());
+        }
+    }
+}
\ No newline at end of file

From 4f354a0b2673e47e0d55c8954503708e38b211df Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 24 Aug 2017 21:06:13 -0500
Subject: [PATCH 007/227] feat(pointers): finish pointer modeling and eval

---
 src/JsonApiDotNetCore/Models/DocumentData.cs  |  2 +-
 .../Models/Operations/Operation.cs            |  4 +-
 .../Models/Operations/Params.cs               | 13 +++++
 .../Models/Pointers/OperationsPointer.cs      | 52 ++++++++++++++-----
 .../Models/Pointers/OperationsPointerTests.cs | 19 +++++++
 5 files changed, 72 insertions(+), 18 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Models/Operations/Params.cs

diff --git a/src/JsonApiDotNetCore/Models/DocumentData.cs b/src/JsonApiDotNetCore/Models/DocumentData.cs
index 32ca6f3f51..8c736f2922 100644
--- a/src/JsonApiDotNetCore/Models/DocumentData.cs
+++ b/src/JsonApiDotNetCore/Models/DocumentData.cs
@@ -13,7 +13,7 @@ public class DocumentData
 
         [JsonProperty("attributes")]
         public Dictionary<string, object> Attributes { get; set; }
-        
+
         [JsonProperty("relationships")]
         public Dictionary<string, RelationshipData> Relationships { get; set; }
     }
diff --git a/src/JsonApiDotNetCore/Models/Operations/Operation.cs b/src/JsonApiDotNetCore/Models/Operations/Operation.cs
index 533af2e109..558d224d04 100644
--- a/src/JsonApiDotNetCore/Models/Operations/Operation.cs
+++ b/src/JsonApiDotNetCore/Models/Operations/Operation.cs
@@ -1,6 +1,4 @@
-using System.Collections;
 using System.Collections.Generic;
-using JsonApiDotNetCore.Controllers;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
 
@@ -15,7 +13,7 @@ public class Operation : DocumentBase
         public ResourceReference Ref { get; set; }
 
         [JsonProperty("params")]
-        public QueryParams Params { get; set; }
+        public Params Params { get; set; }
 
         [JsonProperty("data")]
         public object Data
diff --git a/src/JsonApiDotNetCore/Models/Operations/Params.cs b/src/JsonApiDotNetCore/Models/Operations/Params.cs
new file mode 100644
index 0000000000..470e8f4aa3
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/Operations/Params.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+
+namespace JsonApiDotNetCore.Models.Operations
+{
+    public class Params
+    {
+        public List<string> Include { get; set; }
+        public List<string> Sort { get; set; }
+        public Dictionary<string, object> Filter { get; set; }
+        public string Page { get; set; }
+        public Dictionary<string, object> Fields { get; set; }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
index 5c5d852b25..f245ea4414 100644
--- a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
+++ b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
@@ -15,8 +15,8 @@ public override object GetValue(object root)
         {
             if (root == null) throw new ArgumentNullException(nameof(root));
             if (PointerAddress == null) throw new InvalidOperationException("Cannot get pointer value from null PointerAddress");
-            
-            if (root is List<Operation> operations) 
+
+            if (root is List<Operation> operations)
                 return GetValueFromRoot(operations);
 
             throw new ArgumentException(nameof(root));
@@ -24,16 +24,16 @@ public override object GetValue(object root)
 
         private object GetValueFromRoot(List<Operation> operations)
         {
-            var pathSegments = PointerAddress.Split(new [] { '/' } , StringSplitOptions.RemoveEmptyEntries);
+            var pathSegments = PointerAddress.ToLower().Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
 
-            if(pathSegments.Length < 4)
+            if (pathSegments.Length < 4)
                 throw BadRequestException("number of segments", pathSegments.Length);
 
             if (pathSegments[0] != "operations")
                 throw BadRequestException("prefix", pathSegments[0]);
 
             // /operations/{operationIndex} → operations = [...]
-            if(int.TryParse(pathSegments[1], out int operationIndex))
+            if (int.TryParse(pathSegments[1], out int operationIndex))
                 return GetValueFromOperation(operations[operationIndex], pathSegments);
             else
                 throw BadRequestException("operation index", operationIndex);
@@ -42,32 +42,56 @@ private object GetValueFromRoot(List<Operation> operations)
         private object GetValueFromOperation(Operation operation, string[] pathSegments)
         {
             var operationPropertyName = pathSegments[2];
-            if(operationPropertyName != "data") 
-                throw BadRequestException("operation property name", operationPropertyName);
-            
+
+            // /operations/0/ref → ref = {...}
+            if (operationPropertyName == "ref")
+                return GetValueFromRef(operation.Ref, pathSegments);
+
             // /operations/0/data → data = {...}
-            if(operation.DataIsList ==  false)
+            if (operation.DataIsList == false)
                 return GetValueFromData(operation.DataObject, pathSegments, segementStartIndex: 3);
 
             // /operations/0/data/{dataIndex} → data = [...]
-            if(int.TryParse(pathSegments[3], out int dataIndex)) {
-                if(operation.DataList.Count >= dataIndex - 1)
+            if (int.TryParse(pathSegments[3], out int dataIndex))
+            {
+                if (operation.DataList.Count >= dataIndex - 1)
                     return GetValueFromData(operation.DataList[dataIndex], pathSegments, segementStartIndex: 4);
                 throw BadRequestException("data index", dataIndex, "Pointer references an index in the data array that cannot be found at the specified position.");
             }
-            else {
+            else
+            {
                 throw BadRequestException("data index", dataIndex, "Pointer segement should provide array index but could not be parsed to an integer.");
             }
         }
 
+        private object GetValueFromRef(ResourceReference reference, string[] pathSegments)
+        {
+            const int segementStartIndex = 3;
+
+            // /operations/0/ref/{dataPropertyName}
+            if (pathSegments.Length <= segementStartIndex)
+                throw BadRequestException("length", pathSegments.Length, "Pointer does not contain enough segments to locate ref property.");
+
+            var dataPropertyName = pathSegments[segementStartIndex];
+            switch (dataPropertyName)
+            {
+                case "id":
+                    return reference.Id;
+                case "type":
+                    return reference.Type;
+                default:
+                    throw BadRequestException("ref property name", dataPropertyName, "Only 'id' and 'type' pointers are supported.");
+            }
+        }
+
         private object GetValueFromData(DocumentData data, string[] pathSegments, int segementStartIndex)
         {
             // /operations/0/data/{dataPropertyName}
-            if(pathSegments.Length <= segementStartIndex)
+            if (pathSegments.Length <= segementStartIndex)
                 throw BadRequestException("length", pathSegments.Length, "Pointer does not contain enough segments to locate data property.");
 
             var dataPropertyName = pathSegments[segementStartIndex];
-            switch(dataPropertyName)
+            switch (dataPropertyName)
             {
                 case "id":
                     return data.Id;
diff --git a/test/UnitTests/Models/Pointers/OperationsPointerTests.cs b/test/UnitTests/Models/Pointers/OperationsPointerTests.cs
index 4a82e1a164..9aafc284dc 100644
--- a/test/UnitTests/Models/Pointers/OperationsPointerTests.cs
+++ b/test/UnitTests/Models/Pointers/OperationsPointerTests.cs
@@ -8,6 +8,25 @@ namespace UnitTests.Models.Pointers
 {
     public class OperationsPointerTests
     {
+        [Fact]
+        public void GetValue_Can_Get_Value_From_Ref_Id()
+        {
+            // arrange
+            var json = @"[
+                {
+                    ""op"": ""add"",
+                    ""ref"": {
+                        ""type"": ""articles"",
+                        ""id"": ""1""
+                    }
+                }]";
+            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
+            var pointerJson = @"{ ""pointer"": ""/operations/0/ref/id"" }";
+            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
+            var value = pointer.GetValue(operations);
+            Assert.Equal("1", value.ToString());
+        }
+
         [Fact]
         public void GetValue_Can_Get_Value_From_Data_Id()
         {

From 0d9589090fbf3b1c8334a6714bdf1da5a79b882f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 24 Aug 2017 23:14:38 -0500
Subject: [PATCH 008/227] first pass at pointer replacement and service
 location

---
 .../Builders/ContextGraphBuilder.cs           |  6 ++-
 .../Builders/IContextGraphBuilder.cs          |  3 +-
 .../Data/DefaultEntityRepository.cs           |  2 +-
 .../Internal/ContextEntity.cs                 |  1 +
 .../Generics/GenericProcessorFactory.cs       | 12 ++---
 .../Generics/IGenericProcessorFactory.cs      |  4 +-
 src/JsonApiDotNetCore/Models/DocumentData.cs  | 47 ++++++++++++++++++-
 .../Models/Operations/Operation.cs            | 11 +++++
 .../Models/Pointers/OperationsPointer.cs      |  2 +-
 .../Models/Pointers/Pointer.cs                |  4 +-
 .../Serialization/IJsonApiDeSerializer.cs     |  2 +
 .../Serialization/JsonApiDeSerializer.cs      |  8 ++--
 .../Services/Contract/ICreateService.cs       |  1 -
 .../Services/Contract/IDeleteService.cs       |  1 -
 .../Services/Contract/IGetByIdService.cs      |  1 -
 .../Contract/IGetRelationshipService.cs       |  1 -
 .../Contract/IGetRelationshipsService.cs      |  1 -
 .../Services/Contract/IUpdateService.cs       |  1 -
 .../Services/EntityResourceService.cs         |  2 +-
 .../Services/Operations/CreateOpProcessor.cs  | 41 ++++++++++++++++
 .../Services/Operations/IOpProcessor.cs       | 16 +++++++
 .../Operations/IOperationsProcessor.cs        | 45 ++++++++++++++++++
 .../Operations/OperationProcessorResolver.cs  | 44 +++++++++++++++++
 23 files changed, 228 insertions(+), 28 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs

diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index e47dec2065..c5099bf298 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -28,7 +28,10 @@ public IContextGraph Build()
             return graph;
         }
 
-        public void AddResource<TResource>(string pluralizedTypeName) where TResource : class
+        public void AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>
+            => AddResource<TResource, int>(pluralizedTypeName);
+
+        public void AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>
         {
             var entityType = typeof(TResource);
 
@@ -38,6 +41,7 @@ public void AddResource<TResource>(string pluralizedTypeName) where TResource :
             {
                 EntityName = pluralizedTypeName,
                 EntityType = entityType,
+                IdentityType = typeof(TId),
                 Attributes = GetAttributes(entityType),
                 Relationships = GetRelationships(entityType)
             });
diff --git a/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
index bab62cca64..5844166c18 100644
--- a/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
@@ -8,7 +8,8 @@ public interface IContextGraphBuilder
     {
         Link DocumentLinks  { get; set; }
         IContextGraph Build();
-        void AddResource<TResource>(string pluralizedTypeName) where TResource : class;
+        void AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>;
+        void AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>;
         void AddDbContext<T>() where T : DbContext;
     }
 }
diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index 1199389c60..66804abee5 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -137,7 +137,7 @@ public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
 
         public async Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds)
         {
-            var genericProcessor = _genericProcessorFactory.GetProcessor(relationship.Type);
+            var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(relationship.Type);
             await genericProcessor.UpdateRelationshipsAsync(parent, relationship, relationshipIds);
         }
 
diff --git a/src/JsonApiDotNetCore/Internal/ContextEntity.cs b/src/JsonApiDotNetCore/Internal/ContextEntity.cs
index 4843d245c1..ff539b79ea 100644
--- a/src/JsonApiDotNetCore/Internal/ContextEntity.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextEntity.cs
@@ -8,6 +8,7 @@ public class ContextEntity
     {
         public string EntityName { get; set; }
         public Type EntityType { get; set; }
+        public Type IdentityType { get; set; }
         public List<AttrAttribute> Attributes { get; set; }
         public List<RelationshipAttribute> Relationships { get; set; }
         public Link Links { get; set; } = Link.All;
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
index a238e4ef9f..0918da40d1 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
@@ -1,24 +1,20 @@
 using System;
-using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Internal.Generics
 {
     public class GenericProcessorFactory : IGenericProcessorFactory
     {
-        private readonly DbContext _dbContext;
         private readonly IServiceProvider _serviceProvider;
 
-        public GenericProcessorFactory(DbContext dbContext, 
-            IServiceProvider serviceProvider)
+        public GenericProcessorFactory(IServiceProvider serviceProvider)
         {
-            _dbContext = dbContext;
             _serviceProvider = serviceProvider;
         }
 
-        public IGenericProcessor GetProcessor(Type type)
+        public TInterface GetProcessor<TInterface>(Type[] types)
         {
-            var processorType = typeof(GenericProcessor<>).MakeGenericType(type);
-            return (IGenericProcessor)_serviceProvider.GetService(processorType);
+            var processorType = typeof(GenericProcessor<>).MakeGenericType(types);
+            return (TInterface)_serviceProvider.GetService(processorType);
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs
index 83e794a12b..ecd2c7cdc4 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs
@@ -5,10 +5,12 @@ namespace JsonApiDotNetCore.Internal.Generics
     /// <summary>
     /// Used to generate a generic operations processor when the types
     /// are not know until runtime. The typical use case would be for
+    /// accessing relationship data.be for
     /// accessing relationship data.
     /// </summary>
     public interface IGenericProcessorFactory
     {
-        IGenericProcessor GetProcessor(Type type);
+
+        TInterface GetProcessor<TInterface>(params Type[] types);
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/DocumentData.cs b/src/JsonApiDotNetCore/Models/DocumentData.cs
index 8c736f2922..d87958f37c 100644
--- a/src/JsonApiDotNetCore/Models/DocumentData.cs
+++ b/src/JsonApiDotNetCore/Models/DocumentData.cs
@@ -1,15 +1,18 @@
 using System.Collections.Generic;
+using JsonApiDotNetCore.Models.Pointers;
 using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
 
 namespace JsonApiDotNetCore.Models
 {
     public class DocumentData
     {
         [JsonProperty("type")]
-        public string Type { get; set; }
+        public object Type { get; set; }
 
         [JsonProperty("id")]
-        public string Id { get; set; }
+        public object Id { get; set; }
 
         [JsonProperty("attributes")]
         public Dictionary<string, object> Attributes { get; set; }
@@ -17,4 +20,44 @@ public class DocumentData
         [JsonProperty("relationships")]
         public Dictionary<string, RelationshipData> Relationships { get; set; }
     }
+
+    public class DocumentDataPointerReplacement<TPointer, TPointerBase>
+        where TPointer : Pointer<TPointerBase>, new()
+    {
+        private readonly DocumentData _data;
+
+        public DocumentDataPointerReplacement(DocumentData data)
+        {
+            _data = data;
+        }
+
+        public void ReplacePointers(List<TPointerBase> parentDoc)
+        {
+            ReplacePointer(_data.Id, parentDoc);
+            ReplacePointer(_data.Type, parentDoc);
+        }
+
+        private void ReplacePointer(object reference, List<TPointerBase> parentDoc)
+        {
+            if (reference is JObject jObj)
+                if (jObj.TryParse<TPointer, TPointerBase>(Pointer<TPointerBase>.JsonSchema, out Pointer<TPointerBase> pointer))
+                    reference = pointer.GetValue(parentDoc);
+        }
+    }
 }
+
+public static class JObjectExtensions
+{
+    public static bool TryParse<TPointer, TPointerBase>(this JObject obj, JSchema schema, out Pointer<TPointerBase> pointer)
+      where TPointer : Pointer<TPointerBase>, new()
+    {
+        if (obj.IsValid(schema))
+        {
+            pointer = obj.ToObject<TPointer>();
+            return true;
+        }
+
+        pointer = null;
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Models/Operations/Operation.cs b/src/JsonApiDotNetCore/Models/Operations/Operation.cs
index 558d224d04..1493142b9f 100644
--- a/src/JsonApiDotNetCore/Models/Operations/Operation.cs
+++ b/src/JsonApiDotNetCore/Models/Operations/Operation.cs
@@ -47,5 +47,16 @@ private void SetData(object data)
         public bool DataIsList { get; private set; }
         public List<DocumentData> DataList { get; private set; }
         public DocumentData DataObject { get; private set; }
+
+        public string GetResourceTypeName()
+        {
+            if(Ref != null)
+                return Ref.Type?.ToString();
+
+            if(DataIsList)
+                return DataList[0].Type?.ToString();
+
+            return DataObject.Type?.ToString();
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
index f245ea4414..0df8f64e72 100644
--- a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
+++ b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
@@ -5,7 +5,7 @@
 
 namespace JsonApiDotNetCore.Models.Pointers
 {
-    public class OperationsPointer : Pointer
+    public class OperationsPointer : Pointer<Operation>
     {
         /// <exception cref="System.ArgumentNullException"></exception>
         /// <exception cref="System.ArgumentException"></exception>
diff --git a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs b/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
index ecb25f314c..27f0083904 100644
--- a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
+++ b/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
@@ -3,9 +3,9 @@
 
 namespace JsonApiDotNetCore.Models.Pointers
 {
-    public abstract class Pointer
+    public abstract class Pointer<TPointerBase>
     {
-        private static JSchema JsonSchema { get; } = JSchema.Parse("{ 'pointer': {'type': 'string'} }");
+        public static JSchema JsonSchema { get; } = JSchema.Parse("{ 'pointer': {'type': 'string'} }");
 
         /// <summary>
         /// Location represented by the pointer
diff --git a/src/JsonApiDotNetCore/Serialization/IJsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/IJsonApiDeSerializer.cs
index 5fb91dae36..0355c962ed 100644
--- a/src/JsonApiDotNetCore/Serialization/IJsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/IJsonApiDeSerializer.cs
@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using JsonApiDotNetCore.Models;
 
 namespace JsonApiDotNetCore.Serialization
 {
@@ -8,5 +9,6 @@ public interface IJsonApiDeSerializer
         TEntity Deserialize<TEntity>(string requestBody);
         object DeserializeRelationship(string requestBody);
         List<TEntity> DeserializeList<TEntity>(string requestBody);
+        object DocumentToObject(DocumentData data);
     }
 }
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 021adbe538..a5168f6185 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -78,9 +78,9 @@ public List<TEntity> DeserializeList<TEntity>(string requestBody)
             }
         }
 
-        private object DocumentToObject(DocumentData data)
+        public object DocumentToObject(DocumentData data)
         {
-            var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(data.Type);
+            var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(data.Type?.ToString());
             _jsonApiContext.RequestEntity = contextEntity;
 
             var entity = Activator.CreateInstance(contextEntity.EntityType);
@@ -91,7 +91,7 @@ private object DocumentToObject(DocumentData data)
             var identifiableEntity = (IIdentifiable)entity;
 
             if (data.Id != null)
-                identifiableEntity.StringId = data.Id;
+                identifiableEntity.StringId = data.Id?.ToString();
 
             return identifiableEntity;
         }
@@ -210,7 +210,7 @@ private object SetHasManyRelationship(object entity,
 
                 if (data == null) return entity;
 
-                var genericProcessor = _genericProcessorFactory.GetProcessor(attr.Type);
+                var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(attr.Type);
                 var ids = relationshipData.ManyData.Select(r => r["id"].ToString());
                 genericProcessor.SetRelationships(entity, attr, ids);
             }
diff --git a/src/JsonApiDotNetCore/Services/Contract/ICreateService.cs b/src/JsonApiDotNetCore/Services/Contract/ICreateService.cs
index a4c0cd6cbb..df4916856d 100644
--- a/src/JsonApiDotNetCore/Services/Contract/ICreateService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/ICreateService.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 
diff --git a/src/JsonApiDotNetCore/Services/Contract/IDeleteService.cs b/src/JsonApiDotNetCore/Services/Contract/IDeleteService.cs
index 4ba09fdf40..52e4ca17f4 100644
--- a/src/JsonApiDotNetCore/Services/Contract/IDeleteService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/IDeleteService.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 
diff --git a/src/JsonApiDotNetCore/Services/Contract/IGetByIdService.cs b/src/JsonApiDotNetCore/Services/Contract/IGetByIdService.cs
index 27761abd5d..c01c6a1391 100644
--- a/src/JsonApiDotNetCore/Services/Contract/IGetByIdService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/IGetByIdService.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 
diff --git a/src/JsonApiDotNetCore/Services/Contract/IGetRelationshipService.cs b/src/JsonApiDotNetCore/Services/Contract/IGetRelationshipService.cs
index bd9c0b2be0..de32b77547 100644
--- a/src/JsonApiDotNetCore/Services/Contract/IGetRelationshipService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/IGetRelationshipService.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 
diff --git a/src/JsonApiDotNetCore/Services/Contract/IGetRelationshipsService.cs b/src/JsonApiDotNetCore/Services/Contract/IGetRelationshipsService.cs
index a61cf8f7ac..e519d0b4d1 100644
--- a/src/JsonApiDotNetCore/Services/Contract/IGetRelationshipsService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/IGetRelationshipsService.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 
diff --git a/src/JsonApiDotNetCore/Services/Contract/IUpdateService.cs b/src/JsonApiDotNetCore/Services/Contract/IUpdateService.cs
index ca2e171090..bd5f13dd60 100644
--- a/src/JsonApiDotNetCore/Services/Contract/IUpdateService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/IUpdateService.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index 7db499fd5e..c8c150a108 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -133,7 +133,7 @@ public virtual async Task UpdateRelationshipsAsync(TId id, string relationshipNa
                 .Relationships
                 .FirstOrDefault(r => r.InternalRelationshipName == relationshipName);
 
-            var relationshipIds = relationships.Select(r => r.Id);
+            var relationshipIds = relationships.Select(r => r.Id?.ToString());
 
             await _entities.UpdateRelationshipsAsync(entity, relationship, relationshipIds);
         }
diff --git a/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs
new file mode 100644
index 0000000000..53a91c2fa6
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs
@@ -0,0 +1,41 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Serialization;
+
+namespace JsonApiDotNetCore.Services.Operations
+{
+    public class CreateOpProcessor<T, TId> : IOpProcessor<T, TId>
+         where T : class, IIdentifiable<TId>
+    {
+        private readonly ICreateService<T, TId> _service;
+        private readonly IJsonApiDeSerializer _deSerializer;
+        private readonly IDocumentBuilder _documentBuilder;
+
+        public CreateOpProcessor(
+            ICreateService<T, TId> service,
+            IJsonApiDeSerializer deSerializer,
+            IDocumentBuilder documentBuilder)
+        {
+            _service = service;
+            _deSerializer = deSerializer;
+            _documentBuilder = documentBuilder;
+        }
+
+        public async Task<Operation> ProcessAsync(Operation operation)
+        {
+            var model = (T)_deSerializer.DocumentToObject(operation.DataObject);
+            var result = await _service.CreateAsync(model);
+
+            var operationResult = new Operation {
+                Op = OperationCode.add
+            };
+            
+            operationResult.Data = _documentBuilder.Build(result);
+
+            return operationResult;
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
new file mode 100644
index 0000000000..fe36dd8a9a
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models.Operations;
+
+namespace JsonApiDotNetCore.Services.Operations
+{
+    public interface IOpProcessor
+    {
+        Task<Operation> ProcessAsync(Operation operation);
+    }
+
+    public interface IOpProcessor<T, TId> : IOpProcessor 
+        where T : class, IIdentifiable<TId>
+    { }
+}
diff --git a/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs
new file mode 100644
index 0000000000..8230730d69
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Models.Pointers;
+
+namespace JsonApiDotNetCore.Services.Operations
+{
+    public interface IOperationsProcessor
+    {
+        Task<List<Operation>> ProcessAsync(List<Operation> inputOps);
+    }
+
+    public class OperationsProcessor : IOperationsProcessor
+    {
+        private readonly IOperationProcessorResolver _processorResolver;
+
+        public OperationsProcessor(IOperationProcessorResolver processorResolver)
+        {
+            _processorResolver = processorResolver;
+        }
+        public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
+        {
+            var outputOps = new List<Operation>();
+
+            foreach(var op in inputOps)
+            {
+                // TODO: parse pointers:
+                // locate all objects within the document and replace them
+                var operationsPointer = new OperationsPointer();
+                var replacer = new DocumentDataPointerReplacement<OperationsPointer, Operation>(op.DataObject);
+                replacer.ReplacePointers(outputOps);
+
+                /// 
+                var processor = _processorResolver.LocateCreateService(op);
+                var resultOp = await processor.ProcessAsync(op);
+                outputOps.Add(resultOp);
+            }
+            for(var i=0; i < inputOps.Count; i++)
+            {
+                
+            }
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
new file mode 100644
index 0000000000..98cf03a892
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -0,0 +1,44 @@
+using System.Collections.Concurrent;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Internal.Generics;
+using JsonApiDotNetCore.Models.Operations;
+
+namespace JsonApiDotNetCore.Services.Operations
+{
+    public interface IOperationProcessorResolver
+    {
+        IOpProcessor LocateCreateService(Operation operation);
+    }
+
+    public class OperationProcessorResolver : IOperationProcessorResolver
+    {
+        private readonly IGenericProcessorFactory _processorFactory;
+        private readonly IJsonApiContext _context;
+        private ConcurrentDictionary<string, IOpProcessor> _cachedProcessors = new ConcurrentDictionary<string, IOpProcessor>();
+
+        public OperationProcessorResolver(
+            IGenericProcessorFactory processorFactory,
+            IJsonApiContext context)
+        {
+            _processorFactory = processorFactory;
+            _context = context;
+        }
+
+        // TODO: there may be some optimizations here around the cache such as not caching processors
+        // if the request only contains a single op
+        public IOpProcessor LocateCreateService(Operation operation)
+        {
+            var resource = operation.GetResourceTypeName();
+
+            if (_cachedProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
+                return cachedProcessor;
+
+            var contextEntity = _context.ContextGraph.GetContextEntity();
+            var processor = _processorFactory.GetProcessor<IOpProcessor>(contextEntity.EntityType, contextEntity.IdentityType);
+            
+            _cachedProcessors[resource] = processor;
+            
+            return processor;
+        }
+    }
+}

From 4eb77ec6ed81e1e93a99df55cf6a44b390d04558 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 25 Aug 2017 23:44:00 -0500
Subject: [PATCH 009/227] chore(pointers): move classes into separate files

---
 .../Extensions/JObjectExtensions.cs           | 23 +++++++
 .../Generics/IGenericProcessorFactory.cs      |  1 -
 src/JsonApiDotNetCore/Models/DocumentData.cs  | 43 +------------
 .../Operations/OperationsPointerExchanger.cs  | 62 +++++++++++++++++++
 4 files changed, 86 insertions(+), 43 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs

diff --git a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs b/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
new file mode 100644
index 0000000000..ec997042fb
--- /dev/null
+++ b/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
@@ -0,0 +1,23 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
+using JsonApiDotNetCore.Models.Pointers;
+
+namespace JsonApiDotNetCore.Extensions
+{
+    public static class JObjectExtensions
+    {
+        public static bool TryParse<TPointer, TPointerBase>(this JObject obj, JSchema schema, out Pointer<TPointerBase> pointer)
+        where TPointer : Pointer<TPointerBase>, new()
+        {
+            if (obj.IsValid(schema))
+            {
+                pointer = obj.ToObject<TPointer>();
+                return true;
+            }
+
+            pointer = null;
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs
index ecd2c7cdc4..39df292e14 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs
@@ -10,7 +10,6 @@ namespace JsonApiDotNetCore.Internal.Generics
     /// </summary>
     public interface IGenericProcessorFactory
     {
-
         TInterface GetProcessor<TInterface>(params Type[] types);
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/DocumentData.cs b/src/JsonApiDotNetCore/Models/DocumentData.cs
index d87958f37c..afd9c717cf 100644
--- a/src/JsonApiDotNetCore/Models/DocumentData.cs
+++ b/src/JsonApiDotNetCore/Models/DocumentData.cs
@@ -1,8 +1,7 @@
+using System;
 using System.Collections.Generic;
 using JsonApiDotNetCore.Models.Pointers;
 using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Newtonsoft.Json.Schema;
 
 namespace JsonApiDotNetCore.Models
 {
@@ -20,44 +19,4 @@ public class DocumentData
         [JsonProperty("relationships")]
         public Dictionary<string, RelationshipData> Relationships { get; set; }
     }
-
-    public class DocumentDataPointerReplacement<TPointer, TPointerBase>
-        where TPointer : Pointer<TPointerBase>, new()
-    {
-        private readonly DocumentData _data;
-
-        public DocumentDataPointerReplacement(DocumentData data)
-        {
-            _data = data;
-        }
-
-        public void ReplacePointers(List<TPointerBase> parentDoc)
-        {
-            ReplacePointer(_data.Id, parentDoc);
-            ReplacePointer(_data.Type, parentDoc);
-        }
-
-        private void ReplacePointer(object reference, List<TPointerBase> parentDoc)
-        {
-            if (reference is JObject jObj)
-                if (jObj.TryParse<TPointer, TPointerBase>(Pointer<TPointerBase>.JsonSchema, out Pointer<TPointerBase> pointer))
-                    reference = pointer.GetValue(parentDoc);
-        }
-    }
-}
-
-public static class JObjectExtensions
-{
-    public static bool TryParse<TPointer, TPointerBase>(this JObject obj, JSchema schema, out Pointer<TPointerBase> pointer)
-      where TPointer : Pointer<TPointerBase>, new()
-    {
-        if (obj.IsValid(schema))
-        {
-            pointer = obj.ToObject<TPointer>();
-            return true;
-        }
-
-        pointer = null;
-        return false;
-    }
 }
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs
new file mode 100644
index 0000000000..87a7dbdc25
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using JsonApiDotNetCore.Models.Pointers;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Extensions;
+
+namespace JsonApiDotNetCore.Services.Operations
+{
+    public class DocumentDataPointerReplacement<TPointer, TPointerBase>
+        where TPointer : Pointer<TPointerBase>, new()
+    {
+        private readonly DocumentData _data;
+
+        public DocumentDataPointerReplacement(DocumentData data)
+        {
+            _data = data;
+        }
+
+        public void ReplacePointers(List<TPointerBase> parentDoc)
+        {
+            _data.Id = GetPointerValue(_data.Id, parentDoc);
+            _data.Type = GetPointerValue(_data.Type, parentDoc);
+
+            if (_data.Relationships != null)
+            {
+                foreach (var relationshipDictionary in _data.Relationships)
+                {
+                    if (relationshipDictionary.Value.IsHasMany)
+                    {
+                        foreach (var relationship in relationshipDictionary.Value.ManyData)
+                            ReplaceDictionaryPointers(relationship, parentDoc);
+                    }
+                    else
+                    {
+                        ReplaceDictionaryPointers(relationshipDictionary.Value.SingleData, parentDoc);
+                    }
+                }
+            }
+        }
+
+        private void ReplaceDictionaryPointers(Dictionary<string, object> relationship, List<TPointerBase> parentDoc)
+        {
+            if (relationship.ContainsKey("id"))
+                relationship["id"] = GetPointerValue(relationship["id"], parentDoc);
+
+            if (relationship.ContainsKey("type"))
+                relationship["type"] = GetPointerValue(relationship["type"], parentDoc);
+        }
+
+        private object GetPointerValue(object reference, List<TPointerBase> parentDoc)
+        {
+            if (reference is JObject jObj)
+                if (jObj.TryParse<TPointer, TPointerBase>(Pointer<TPointerBase>.JsonSchema, out Pointer<TPointerBase> pointer))
+                    return pointer.GetValue(parentDoc);
+
+            return reference;
+        }
+    }
+}
\ No newline at end of file

From 63827cd3f77db64c39777dac8698011291de1330 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 25 Aug 2017 23:44:27 -0500
Subject: [PATCH 010/227] feat(RelationshipData): expose IsHasMany property

---
 .../Models/RelationshipData.cs                | 40 ++++++---
 .../UnitTests/Models/RelationshipDataTests.cs | 90 +++++++++++++++++++
 2 files changed, 116 insertions(+), 14 deletions(-)
 create mode 100644 test/UnitTests/Models/RelationshipDataTests.cs

diff --git a/src/JsonApiDotNetCore/Models/RelationshipData.cs b/src/JsonApiDotNetCore/Models/RelationshipData.cs
index f74651318e..d81b2fe75a 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipData.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipData.cs
@@ -11,29 +11,41 @@ public class RelationshipData
         public Links Links { get; set; }
 
         [JsonProperty("data")]
-        public object ExposedData { 
-            get {
-                if(ManyData != null)
+        public object ExposedData
+        {
+            get
+            {
+                if (ManyData != null)
                     return ManyData;
                 return SingleData;
             }
-            set {
-                if(value is IEnumerable)
-                    if(value is JObject jObject)
-                        SingleData = jObject.ToObject<Dictionary<string, object>>();   
-                    else if(value is JArray jArray)
-                        ManyData = jArray.ToObject<List<Dictionary<string, object>>>();
-                    else
-                        ManyData = (List<Dictionary<string, object>>)value;
-                else
+            set
+            {
+                if (value is JObject jObject)
+                    SingleData = jObject.ToObject<Dictionary<string, object>>();
+                else if (value is Dictionary<string, object> dict)
                     SingleData = (Dictionary<string, object>)value;
+                else
+                    SetManyData(value);
             }
-         }
+        }
+
+        private void SetManyData(object value)
+        {
+            IsHasMany = true;
+            if (value is JArray jArray)
+                ManyData = jArray.ToObject<List<Dictionary<string, object>>>();
+            else
+                ManyData = (List<Dictionary<string, object>>)value;
+        }
 
         [JsonIgnore]
         public List<Dictionary<string, object>> ManyData { get; set; }
-        
+
         [JsonIgnore]
         public Dictionary<string, object> SingleData { get; set; }
+
+        [JsonIgnore]
+        public bool IsHasMany { get; private set; }
     }
 }
diff --git a/test/UnitTests/Models/RelationshipDataTests.cs b/test/UnitTests/Models/RelationshipDataTests.cs
new file mode 100644
index 0000000000..780a5faa0b
--- /dev/null
+++ b/test/UnitTests/Models/RelationshipDataTests.cs
@@ -0,0 +1,90 @@
+using JsonApiDotNetCore.Models;
+using System.Collections.Generic;
+using Xunit;
+using Newtonsoft.Json.Linq;
+
+namespace UnitTests.Models
+{
+    public class RelationshipDataTests
+    {
+        [Fact]
+        public void Setting_ExposedData_To_List_Sets_ManyData()
+        {
+            // arrange
+            var relationshipData = new RelationshipData();
+            var relationships = new List<Dictionary<string, object>> {
+                new Dictionary<string, object> {
+                    { "authors", new { } }
+                }
+            };
+
+            // act 
+            relationshipData.ExposedData = relationships;
+
+            // assert
+            Assert.NotEmpty(relationshipData.ManyData);
+            Assert.True(relationshipData.ManyData[0].ContainsKey("authors"));
+            Assert.True(relationshipData.IsHasMany);
+        }
+
+        [Fact]
+        public void Setting_ExposedData_To_JArray_Sets_ManyData()
+        {
+            // arrange
+            var relationshipData = new RelationshipData();
+            var relationshipsJson = @"[
+                {
+                    ""authors"": {}
+                }
+            ]";
+
+            var relationships = JArray.Parse(relationshipsJson);
+
+            // act 
+            relationshipData.ExposedData = relationships;
+
+            // assert
+            Assert.NotEmpty(relationshipData.ManyData);
+            Assert.True(relationshipData.ManyData[0].ContainsKey("authors"));
+            Assert.True(relationshipData.IsHasMany);
+        }
+
+        [Fact]
+        public void Setting_ExposedData_To_Dictionary_Sets_SingleData()
+        {
+            // arrange
+            var relationshipData = new RelationshipData();
+            var relationship = new Dictionary<string, object> {
+                { "authors", new { } }
+            };
+
+            // act 
+            relationshipData.ExposedData = relationship;
+
+            // assert
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.True(relationshipData.SingleData.ContainsKey("authors"));
+            Assert.False(relationshipData.IsHasMany);
+        }
+
+        [Fact]
+        public void Setting_ExposedData_To_JObject_Sets_SingleData()
+        {
+            // arrange
+            var relationshipData = new RelationshipData();
+            var relationshipJson = @"{
+                    ""authors"": {}
+                }";
+
+            var relationship = JObject.Parse(relationshipJson);
+
+            // act 
+            relationshipData.ExposedData = relationship;
+
+            // assert
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.True(relationshipData.SingleData.ContainsKey("authors"));
+            Assert.False(relationshipData.IsHasMany);
+        }
+    }
+}

From 8f8d76ff2caaa9bc59e1dfe772dabac85ead5fc1 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 25 Aug 2017 23:45:23 -0500
Subject: [PATCH 011/227] test(OperationsProcessor): performs pointer
 substitution

---
 .../Operations/IOperationsProcessor.cs        | 10 +-
 .../Operations/OperationProcessorResolver.cs  |  3 +-
 .../Operations/OperationsProcessorTests.cs    | 94 +++++++++++++++++++
 3 files changed, 100 insertions(+), 7 deletions(-)
 create mode 100644 test/UnitTests/Services/Operations/OperationsProcessorTests.cs

diff --git a/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs
index 8230730d69..0158caa081 100644
--- a/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs
@@ -19,6 +19,7 @@ public OperationsProcessor(IOperationProcessorResolver processorResolver)
         {
             _processorResolver = processorResolver;
         }
+        
         public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
         {
             var outputOps = new List<Operation>();
@@ -31,15 +32,14 @@ public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
                 var replacer = new DocumentDataPointerReplacement<OperationsPointer, Operation>(op.DataObject);
                 replacer.ReplacePointers(outputOps);
 
-                /// 
                 var processor = _processorResolver.LocateCreateService(op);
                 var resultOp = await processor.ProcessAsync(op);
-                outputOps.Add(resultOp);
-            }
-            for(var i=0; i < inputOps.Count; i++)
-            {
                 
+                if(resultOp != null)
+                    outputOps.Add(resultOp);
             }
+
+            return outputOps;
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
index 98cf03a892..b56eb11bd6 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -1,5 +1,4 @@
 using System.Collections.Concurrent;
-using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models.Operations;
 
@@ -33,7 +32,7 @@ public IOpProcessor LocateCreateService(Operation operation)
             if (_cachedProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
                 return cachedProcessor;
 
-            var contextEntity = _context.ContextGraph.GetContextEntity();
+            var contextEntity = _context.ContextGraph.GetContextEntity(resource);
             var processor = _processorFactory.GetProcessor<IOpProcessor>(contextEntity.EntityType, contextEntity.IdentityType);
             
             _cachedProcessors[resource] = processor;
diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
new file mode 100644
index 0000000000..fadcd3be78
--- /dev/null
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -0,0 +1,94 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Services.Operations;
+using Moq;
+using Newtonsoft.Json;
+using Xunit;
+
+namespace UnitTests.Services
+{
+    public class OperationsProcessorTests
+    {
+        private readonly Mock<IOperationProcessorResolver> _resolverMock;
+
+        public OperationsProcessorTests()
+        {
+            _resolverMock = new Mock<IOperationProcessorResolver>();
+        }
+
+        [Fact]
+        public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
+        {
+            // arrange
+            var request = @"[
+                {
+                    ""op"": ""add"",
+                    ""data"": {
+                        ""type"": ""authors"",
+                        ""attributes"": {
+                            ""name"": ""dgeb""
+                        }
+                    }
+                }, {
+                    ""op"": ""add"",
+                    ""data"": {
+                        ""type"": ""articles"",
+                        ""attributes"": {
+                            ""title"": ""JSON API paints my bikeshed!""
+                        },
+                        ""relationships"": {
+                            ""author"": {
+                                ""data"": {
+                                    ""type"": ""authors"",
+                                    ""id"": { ""pointer"": ""/operations/0/data/id"" }
+                                }
+                            }
+                        }
+                    }
+                }
+            ]";
+
+            var op1Result = @"{
+                ""links"": {
+                    ""self"": ""http://example.com/authors/9""
+                },
+                ""data"": {
+                    ""type"": ""authors"",
+                    ""id"": ""9"",
+                    ""attributes"": {
+                        ""name"": ""dgeb""
+                    }
+                }
+            }";
+                
+            var operations = JsonConvert.DeserializeObject<List<Operation>>(request);
+            var addOperationResult = JsonConvert.DeserializeObject<Operation>(op1Result);
+
+            var opProcessorMock = new Mock<IOpProcessor>();
+            opProcessorMock.Setup(m => m.ProcessAsync(It.Is<Operation>(op => op.DataObject.Type.ToString() == "authors")))
+                .ReturnsAsync(addOperationResult);
+            
+            _resolverMock.Setup(m => m.LocateCreateService(It.IsAny<Operation>()))
+                .Returns(opProcessorMock.Object);
+            
+            _resolverMock.Setup(m => m.LocateCreateService((It.IsAny<Operation>())))
+                .Returns(opProcessorMock.Object);
+
+            var operationsProcessor = new OperationsProcessor(_resolverMock.Object);
+
+            // act
+            var results = await operationsProcessor.ProcessAsync(operations);
+
+            // assert
+            opProcessorMock.Verify(
+                m => m.ProcessAsync(
+                    It.Is<Operation>(o => 
+                        o.DataObject.Type.ToString() == "articles"
+                        && o.DataObject.Relationships["author"].SingleData["id"].ToString() == "9"
+                    )
+                )
+            );
+        }
+    }
+}

From 97c27e056cc3c06cf79c06f646831ddbb041f2d4 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 25 Aug 2017 23:48:06 -0500
Subject: [PATCH 012/227] style(*): naming conventions and namespacr cleanup

---
 src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs          | 1 -
 src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs | 1 -
 src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs      | 1 -
 .../Services/Operations/OperationsPointerExchanger.cs          | 3 ---
 .../{IOperationsProcessor.cs => OperationsProcessor.cs}        | 1 -
 5 files changed, 7 deletions(-)
 rename src/JsonApiDotNetCore/Services/Operations/{IOperationsProcessor.cs => OperationsProcessor.cs} (97%)

diff --git a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs b/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
index ec997042fb..70aa070fc6 100644
--- a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
@@ -1,4 +1,3 @@
-using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
 using Newtonsoft.Json.Schema;
 using JsonApiDotNetCore.Models.Pointers;
diff --git a/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs
index 53a91c2fa6..1c8fb50603 100644
--- a/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Models;
diff --git a/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
index fe36dd8a9a..67cd0896ec 100644
--- a/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs
index 87a7dbdc25..7301353c3e 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs
@@ -1,9 +1,6 @@
-using System;
 using System.Collections.Generic;
 using JsonApiDotNetCore.Models.Pointers;
-using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
-using Newtonsoft.Json.Schema;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Extensions;
 
diff --git a/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
similarity index 97%
rename from src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs
rename to src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index 0158caa081..9449564f22 100644
--- a/src/JsonApiDotNetCore/Services/Operations/IOperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -1,6 +1,5 @@
 using System.Collections.Generic;
 using System.Threading.Tasks;
-using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Models.Pointers;
 

From 5cda230eba1e1d8b08ce30e7053d06f92d55dc1d Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 25 Aug 2017 23:48:59 -0500
Subject: [PATCH 013/227] style(processors): create namespace for individual
 processors

---
 .../Services/Operations/{ => Processors}/CreateOpProcessor.cs   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 rename src/JsonApiDotNetCore/Services/Operations/{ => Processors}/CreateOpProcessor.cs (95%)

diff --git a/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
similarity index 95%
rename from src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs
rename to src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
index 1c8fb50603..3004ba15ef 100644
--- a/src/JsonApiDotNetCore/Services/Operations/CreateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
@@ -4,7 +4,7 @@
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Serialization;
 
-namespace JsonApiDotNetCore.Services.Operations
+namespace JsonApiDotNetCore.Services.Operations.Processors
 {
     public class CreateOpProcessor<T, TId> : IOpProcessor<T, TId>
          where T : class, IIdentifiable<TId>

From fbb698d5f5249c32687de027baf3036e57c641fa Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 26 Aug 2017 20:50:51 -0500
Subject: [PATCH 014/227] test(CreateOpProcessor): test and implement the
 create op processor

---
 .../Builders/ContextGraphBuilder.cs           | 10 ++-
 .../Builders/DocumentBuilder.cs               |  2 +-
 .../Builders/IContextGraphBuilder.cs          |  6 +-
 .../Builders/IDocumentBuilder.cs              |  2 +
 src/JsonApiDotNetCore/Models/DocumentData.cs  |  2 -
 .../Processors/CreateOpProcessor.cs           | 22 ++++-
 .../Processors/CreateOpProcessorTests.cs      | 80 +++++++++++++++++++
 7 files changed, 113 insertions(+), 11 deletions(-)
 create mode 100644 test/UnitTests/Services/Operations/Processors/CreateOpProcessorTests.cs

diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index c5099bf298..efbc0535e1 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -28,10 +28,10 @@ public IContextGraph Build()
             return graph;
         }
 
-        public void AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>
+        public IContextGraphBuilder AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>
             => AddResource<TResource, int>(pluralizedTypeName);
 
-        public void AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>
+        public IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>
         {
             var entityType = typeof(TResource);
 
@@ -45,6 +45,8 @@ public void AddResource<TResource, TId>(string pluralizedTypeName) where TResour
                 Attributes = GetAttributes(entityType),
                 Relationships = GetRelationships(entityType)
             });
+
+            return this;
         }
 
         private Link GetLinkFlags(Type entityType)
@@ -97,7 +99,7 @@ protected virtual Type GetRelationshipType(RelationshipAttribute relation, Prope
                 return prop.PropertyType;
         }
 
-        public void AddDbContext<T>() where T : DbContext
+        public IContextGraphBuilder AddDbContext<T>() where T : DbContext
         {
             _usesDbContext = true;
 
@@ -125,6 +127,8 @@ public void AddDbContext<T>() where T : DbContext
                     });
                 }
             }
+
+            return this;
         }
 
         private string GetResourceName(PropertyInfo property)
diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index ae102111c3..c6439efbc8 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -104,7 +104,7 @@ private List<DocumentData> AppendIncludedObject(List<DocumentData> includedObjec
             return includedObject;
         }
 
-        private DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
+        public DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
         {
             var data = new DocumentData
             {
diff --git a/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
index 5844166c18..9f3c7bd1a8 100644
--- a/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
@@ -8,8 +8,8 @@ public interface IContextGraphBuilder
     {
         Link DocumentLinks  { get; set; }
         IContextGraph Build();
-        void AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>;
-        void AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>;
-        void AddDbContext<T>() where T : DbContext;
+        IContextGraphBuilder AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>;
+        IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>;
+        IContextGraphBuilder AddDbContext<T>() where T : DbContext;
     }
 }
diff --git a/src/JsonApiDotNetCore/Builders/IDocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/IDocumentBuilder.cs
index 8fe5c65ae9..4fbc8df01b 100644
--- a/src/JsonApiDotNetCore/Builders/IDocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/IDocumentBuilder.cs
@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 
 namespace JsonApiDotNetCore.Builders
@@ -7,5 +8,6 @@ public interface IDocumentBuilder
     {
         Document Build(IIdentifiable entity);
         Documents Build(IEnumerable<IIdentifiable> entities);
+        DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity);
     }
 }
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Models/DocumentData.cs b/src/JsonApiDotNetCore/Models/DocumentData.cs
index afd9c717cf..f4a3c137ae 100644
--- a/src/JsonApiDotNetCore/Models/DocumentData.cs
+++ b/src/JsonApiDotNetCore/Models/DocumentData.cs
@@ -1,6 +1,4 @@
-using System;
 using System.Collections.Generic;
-using JsonApiDotNetCore.Models.Pointers;
 using Newtonsoft.Json;
 
 namespace JsonApiDotNetCore.Models
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
index 3004ba15ef..8ef9298027 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
@@ -1,26 +1,42 @@
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Serialization;
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
+    public class CreateOpProcessor<T> : CreateOpProcessor<T, int>
+        where T : class, IIdentifiable<int>
+    {
+        public CreateOpProcessor(
+            ICreateService<T, int> service,
+            IJsonApiDeSerializer deSerializer,
+            IDocumentBuilder documentBuilder,
+            IContextGraph contextGraph
+        ) : base(service, deSerializer, documentBuilder, contextGraph)
+        { }
+    }
+
     public class CreateOpProcessor<T, TId> : IOpProcessor<T, TId>
          where T : class, IIdentifiable<TId>
     {
         private readonly ICreateService<T, TId> _service;
         private readonly IJsonApiDeSerializer _deSerializer;
         private readonly IDocumentBuilder _documentBuilder;
+        private readonly IContextGraph _contextGraph;
 
         public CreateOpProcessor(
             ICreateService<T, TId> service,
             IJsonApiDeSerializer deSerializer,
-            IDocumentBuilder documentBuilder)
+            IDocumentBuilder documentBuilder,
+            IContextGraph contextGraph)
         {
             _service = service;
             _deSerializer = deSerializer;
             _documentBuilder = documentBuilder;
+            _contextGraph = contextGraph;
         }
 
         public async Task<Operation> ProcessAsync(Operation operation)
@@ -32,7 +48,9 @@ public async Task<Operation> ProcessAsync(Operation operation)
                 Op = OperationCode.add
             };
             
-            operationResult.Data = _documentBuilder.Build(result);
+            operationResult.Data = _documentBuilder.GetData(
+                _contextGraph.GetContextEntity(operation.GetResourceTypeName()), 
+                result);
 
             return operationResult;
         }
diff --git a/test/UnitTests/Services/Operations/Processors/CreateOpProcessorTests.cs b/test/UnitTests/Services/Operations/Processors/CreateOpProcessorTests.cs
new file mode 100644
index 0000000000..9e33af63c2
--- /dev/null
+++ b/test/UnitTests/Services/Operations/Processors/CreateOpProcessorTests.cs
@@ -0,0 +1,80 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Serialization;
+using JsonApiDotNetCore.Services;
+using JsonApiDotNetCore.Services.Operations.Processors;
+using Moq;
+using Xunit;
+
+namespace UnitTests.Services
+{
+    public class CreateOpProcessorTests
+    {
+        private readonly Mock<ICreateService<TestResource>> _createServiceMock;
+        private readonly Mock<IJsonApiDeSerializer> _deserializerMock;
+        private readonly Mock<IDocumentBuilder> _documentBuilderMock;
+
+        public CreateOpProcessorTests()
+        {
+            _createServiceMock = new Mock<ICreateService<TestResource>>();
+            _deserializerMock = new Mock<IJsonApiDeSerializer>();
+            _documentBuilderMock = new Mock<IDocumentBuilder>();
+        }
+
+        [Fact]
+        public async Task ProcessAsync_Deserializes_And_Creates()
+        {
+            // arrange
+            var testResource = new TestResource {
+                Name = "some-name"
+            };
+
+            var data = new DocumentData {
+                Type = "test-resources",
+                Attributes = new Dictionary<string, object> {
+                    { "name", testResource.Name }
+                }
+            };
+
+            var operation = new Operation {
+                Data = data,                
+            };
+
+            var contextGraph = new ContextGraphBuilder()
+                .AddResource<TestResource>("test-resources")
+                .Build();
+
+            _deserializerMock.Setup(m => m.DocumentToObject(It.IsAny<DocumentData>()))
+                .Returns(testResource);
+
+            var opProcessor = new CreateOpProcessor<TestResource>(
+                _createServiceMock.Object,
+                _deserializerMock.Object,
+                _documentBuilderMock.Object,
+                contextGraph
+            );
+
+            _documentBuilderMock.Setup(m => m.GetData(It.IsAny<ContextEntity>(), It.IsAny<TestResource>()))
+                .Returns(data);
+
+            // act
+            var result = await opProcessor.ProcessAsync(operation);
+
+            // assert
+            Assert.Equal(OperationCode.add, result.Op);
+            Assert.NotNull(result.Data);
+            Assert.Equal(testResource.Name, result.DataObject.Attributes["name"]);
+            _createServiceMock.Verify(m => m.CreateAsync(It.IsAny<TestResource>()));
+        }
+
+        public class TestResource : Identifiable
+        {
+            [Attr("name")]
+            public string Name { get; set; }
+        }
+    }
+}

From 030599316cd0d29eeb93e4bf953cb3e603bd70a5 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 26 Aug 2017 21:11:58 -0500
Subject: [PATCH 015/227] feat(content-negotiation): wire up reader and input
 formatter

---
 .../JsonApiOperationsInputFormatter.cs        | 33 ++++++++++++++
 .../Formatters/JsonApiOperationsReader.cs     | 44 +++++++++++++++++++
 2 files changed, 77 insertions(+)
 create mode 100644 src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
 create mode 100644 src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs

diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
new file mode 100644
index 0000000000..61ae97ffbb
--- /dev/null
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc.Formatters;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Primitives;
+
+namespace JsonApiDotNetCore.Formatters
+{
+    public class JsonApiOperationsInputFormatter : IInputFormatter
+    {
+        const string PROFILE_EXTENSION = "<http://example.org/profiles/myjsonstuff>; rel=\"profile\"";
+
+        public bool CanRead(InputFormatterContext context)
+        {
+            if (context == null)
+                throw new ArgumentNullException(nameof(context));
+
+            var contentTypeString = context.HttpContext.Request.ContentType;
+
+            return (
+                contentTypeString == "application/vnd.api+json" && 
+                context.HttpContext.Request.Headers.TryGetValue("Link", out StringValues profileExtension) &&
+                profileExtension == PROFILE_EXTENSION
+            );
+        }
+
+        public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
+        {
+            var reader = context.HttpContext.RequestServices.GetService<IJsonApiOperationsReader>();
+            return await reader.ReadAsync(context);
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
new file mode 100644
index 0000000000..f586d2e7e9
--- /dev/null
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
@@ -0,0 +1,44 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Serialization;
+using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Mvc.Formatters;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+
+namespace JsonApiDotNetCore.Formatters
+{
+    public interface IJsonApiOperationsReader
+    {
+        Task<InputFormatterResult> ReadAsync(InputFormatterContext context);
+    }
+
+    public class JsonApiOperationsReader : IJsonApiOperationsReader
+    {
+        public JsonApiOperationsReader()
+        {
+        }
+
+        public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
+        {
+            if (context == null)
+                throw new ArgumentNullException(nameof(context));
+
+            var request = context.HttpContext.Request;
+            if (request.ContentLength == 0)
+                return InputFormatterResult.FailureAsync();
+
+            return InputFormatterResult.SuccessAsync(null);
+        }
+
+        private string GetRequestBody(Stream body)
+        {
+            using (var reader = new StreamReader(body))
+            {
+                return reader.ReadToEnd();
+            }
+        }
+    }
+}
\ No newline at end of file

From 4055b4102385bc460ca00764200993b4d6dbe6c4 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 27 Aug 2017 18:09:00 -0500
Subject: [PATCH 016/227] feat(reader): deserialize operations document

---
 .../Formatters/JsonApiOperationsReader.cs       | 17 ++++++-----------
 .../Models/Operations/OperationsDocument.cs     |  9 +++++++++
 2 files changed, 15 insertions(+), 11 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Models/Operations/OperationsDocument.cs

diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
index f586d2e7e9..3fc4524b9b 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
@@ -1,11 +1,8 @@
 using System;
 using System.IO;
 using System.Threading.Tasks;
-using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Serialization;
-using JsonApiDotNetCore.Services;
+using JsonApiDotNetCore.Models.Operations;
 using Microsoft.AspNetCore.Mvc.Formatters;
-using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
 
 namespace JsonApiDotNetCore.Formatters
@@ -17,28 +14,26 @@ public interface IJsonApiOperationsReader
 
     public class JsonApiOperationsReader : IJsonApiOperationsReader
     {
-        public JsonApiOperationsReader()
-        {
-        }
-
         public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
         {
             if (context == null)
                 throw new ArgumentNullException(nameof(context));
 
             var request = context.HttpContext.Request;
-            if (request.ContentLength == 0)
+            if (request.ContentLength == null || request.ContentLength == 0)
                 return InputFormatterResult.FailureAsync();
 
+            var body = GetRequestBody(request.Body);
+
+            var operations = JsonConvert.DeserializeObject<OperationsDocument>(body);
+
             return InputFormatterResult.SuccessAsync(null);
         }
 
         private string GetRequestBody(Stream body)
         {
             using (var reader = new StreamReader(body))
-            {
                 return reader.ReadToEnd();
-            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Models/Operations/OperationsDocument.cs b/src/JsonApiDotNetCore/Models/Operations/OperationsDocument.cs
new file mode 100644
index 0000000000..987f9abc20
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/Operations/OperationsDocument.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace JsonApiDotNetCore.Models.Operations
+{
+    public class OperationsDocument
+    {
+        public List<Operation> Operations { get; set; }
+    }
+}

From 2b59bdff4da9c131bdb637bbae95404a6c783679 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 28 Aug 2017 20:01:23 -0500
Subject: [PATCH 017/227] feat(*): add controller, input formatter, and
 services

---
 JsonApiDotnetCore.sln                         | 15 ++++++++++++
 .../Configuration/JsonApiOptions.cs           |  8 +++++++
 .../Controllers/BaseJsonApiController.cs      |  1 -
 .../JsonApiOperationsController.cs            | 24 +++++++++++++++++++
 .../IServiceCollectionExtensions.cs           | 15 ++++++++++++
 .../Formatters/JsonApiInputFormatter.cs       |  9 +++++--
 .../JsonApiOperationsInputFormatter.cs        | 22 +++++++++++++----
 .../Formatters/JsonApiOperationsReader.cs     |  6 ++++-
 .../Models/JsonApiExtension.cs                |  7 ++++++
 9 files changed, 98 insertions(+), 9 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
 create mode 100644 src/JsonApiDotNetCore/Models/JsonApiExtension.cs

diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index b4ff89b0aa..74ea28c41a 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -28,6 +28,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{02
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReportsExample", "src\Examples\ReportsExample\ReportsExample.csproj", "{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OperationsExample", "src\Examples\OperationsExample\OperationsExample.csproj", "{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -110,6 +112,18 @@ Global
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|x64
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|x86
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|x86
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.ActiveCfg = Debug|x64
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.Build.0 = Debug|x64
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.ActiveCfg = Debug|x86
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.Build.0 = Debug|x86
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.ActiveCfg = Release|x64
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.Build.0 = Release|x64
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.ActiveCfg = Release|x86
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -123,5 +137,6 @@ Global
 		{6D4BD85A-A262-44C6-8572-FE3A30410BF3} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
 		{026FBC6C-AF76-4568-9B87-EC73457899FD} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
 	EndGlobalSection
 EndGlobal
diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index 26e16b0741..be22f8af07 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -1,6 +1,8 @@
 using System;
+using System.Collections.Generic;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Serialization;
 using Microsoft.EntityFrameworkCore;
 using Newtonsoft.Json;
@@ -30,6 +32,7 @@ public IContractResolver JsonContractResolver
             ContractResolver = new DasherizedResolver()
         };
         internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder();
+        internal List<JsonApiExtension> EnabledExtensions { get; set; } = new List<JsonApiExtension>();
 
         public void BuildContextGraph<TContext>(Action<IContextGraphBuilder> builder) where TContext : DbContext
         {
@@ -48,5 +51,10 @@ public void BuildContextGraph(Action<IContextGraphBuilder> builder)
 
             ContextGraph = ContextGraphBuilder.Build();
         }
+
+        public void EnableExtension(JsonApiExtension extension)
+        {
+            EnabledExtensions.Add(extension);
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
index a10ea381de..8785eb2266 100644
--- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
+++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
@@ -4,7 +4,6 @@
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
 
 namespace JsonApiDotNetCore.Controllers
 {
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
new file mode 100644
index 0000000000..40ac76fea3
--- /dev/null
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
@@ -0,0 +1,24 @@
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Services.Operations;
+using Microsoft.AspNetCore.Mvc;
+
+namespace JsonApiDotNetCore.Controllers
+{
+    public class JsonApiOperationsController : Controller
+    {
+        private readonly IOperationsProcessor _operationsProcessor;
+
+        public JsonApiOperationsController(IOperationsProcessor operationsProcessor)
+        {
+            _operationsProcessor = operationsProcessor;
+        }
+
+        [HttpPost("bulk")]
+        public async Task<IActionResult> PatchAsync(OperationsDocument doc)
+        {
+            var results = await _operationsProcessor.ProcessAsync(doc.Operations);
+            return Ok(results);
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index afcc11ee8d..6cd84d397c 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -6,8 +6,10 @@
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Middleware;
+using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
+using JsonApiDotNetCore.Services.Operations;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.EntityFrameworkCore;
@@ -91,6 +93,9 @@ public static void AddJsonApiInternals(
                 services.AddSingleton<DbContextOptions>(new DbContextOptionsBuilder().Options);
             }
 
+            if (jsonApiOptions.EnabledExtensions.Contains(JsonApiExtension.Operations))
+                AddOperationServices(services);
+
             services.AddScoped<IDbContextResolver, DbContextResolver>();
             services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
             services.AddScoped(typeof(IEntityRepository<,>), typeof(DefaultEntityRepository<,>));
@@ -114,8 +119,18 @@ public static void AddJsonApiInternals(
             services.AddScoped<IControllerContext, Services.ControllerContext>();
         }
 
+        private static void AddOperationServices(IServiceCollection services)
+        {
+            services.AddScoped<IOperationsProcessor, OperationsProcessor>();
+            services.AddSingleton<IOperationProcessorResolver, OperationProcessorResolver>();
+            services.AddSingleton<IGenericProcessorFactory, GenericProcessorFactory>();
+        }
+
         public static void SerializeAsJsonApi(this MvcOptions options, JsonApiOptions jsonApiOptions)
         {
+            if (jsonApiOptions.EnabledExtensions.Contains(JsonApiExtension.Operations))
+                options.InputFormatters.Insert(0, new JsonApiOperationsInputFormatter());
+
             options.InputFormatters.Insert(0, new JsonApiInputFormatter());
 
             options.OutputFormatters.Insert(0, new JsonApiOutputFormatter());
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
index 12e57deadf..f5b822fd62 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
@@ -8,17 +8,22 @@ namespace JsonApiDotNetCore.Formatters
     public class JsonApiInputFormatter : IInputFormatter
     {
         public bool CanRead(InputFormatterContext context)
-        {
+        {            
             if (context == null)
                 throw new ArgumentNullException(nameof(context));
 
             var contentTypeString = context.HttpContext.Request.ContentType;
 
-            return contentTypeString == "application/vnd.api+json";
+            var canRead = contentTypeString == "application/vnd.api+json";
+
+            Console.WriteLine($">>> JsonApiInputFormatter Can Read {canRead}");
+
+            return canRead;
         }
 
         public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
         {
+            Console.WriteLine($">>> JsonApiInputFormatter ReadAsync");
             var reader = context.HttpContext.RequestServices.GetService<IJsonApiReader>();
             return await reader.ReadAsync(context);
         }
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
index 61ae97ffbb..0f83c1f031 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
@@ -1,31 +1,43 @@
 using System;
+using System.Text;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Mvc.Formatters;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Primitives;
+using Microsoft.Net.Http.Headers;
 
 namespace JsonApiDotNetCore.Formatters
 {
-    public class JsonApiOperationsInputFormatter : IInputFormatter
+    public class JsonApiOperationsInputFormatter : TextInputFormatter
     {
         const string PROFILE_EXTENSION = "<http://example.org/profiles/myjsonstuff>; rel=\"profile\"";
 
-        public bool CanRead(InputFormatterContext context)
+        public JsonApiOperationsInputFormatter()
+        {
+            SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/vnd.api+json"));
+            SupportedEncodings.Add(Encoding.UTF8);
+            SupportedEncodings.Add(Encoding.Unicode);
+        }
+
+        public override bool CanRead(InputFormatterContext context)
         {
             if (context == null)
                 throw new ArgumentNullException(nameof(context));
 
             var contentTypeString = context.HttpContext.Request.ContentType;
 
-            return (
-                contentTypeString == "application/vnd.api+json" && 
+            var canRead = (
+                contentTypeString == "application/vnd.api+json" &&
                 context.HttpContext.Request.Headers.TryGetValue("Link", out StringValues profileExtension) &&
                 profileExtension == PROFILE_EXTENSION
             );
+            Console.WriteLine($">>> JsonApiOperationsInputFormatter Can Read {canRead}");
+            return canRead;
         }
 
-        public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
+        public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
         {
+            Console.WriteLine($">>> JsonApiOperationsInputFormatter ReadAsync");
             var reader = context.HttpContext.RequestServices.GetService<IJsonApiOperationsReader>();
             return await reader.ReadAsync(context);
         }
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
index 3fc4524b9b..9cfc4c177b 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
@@ -1,6 +1,7 @@
 using System;
 using System.IO;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models.Operations;
 using Microsoft.AspNetCore.Mvc.Formatters;
 using Newtonsoft.Json;
@@ -27,7 +28,10 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
 
             var operations = JsonConvert.DeserializeObject<OperationsDocument>(body);
 
-            return InputFormatterResult.SuccessAsync(null);
+            if(operations == null)
+                throw new JsonApiException(400, "Failed to deserialize operations request.");
+
+            return InputFormatterResult.SuccessAsync(operations);
         }
 
         private string GetRequestBody(Stream body)
diff --git a/src/JsonApiDotNetCore/Models/JsonApiExtension.cs b/src/JsonApiDotNetCore/Models/JsonApiExtension.cs
new file mode 100644
index 0000000000..7d3b0c87ea
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/JsonApiExtension.cs
@@ -0,0 +1,7 @@
+namespace JsonApiDotNetCore.Models
+{
+    public enum JsonApiExtension
+    {
+        Operations = 0
+    }
+}

From 3c8e3620a55d2418812a1c126bcd9d3f87db8583 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 28 Aug 2017 20:01:39 -0500
Subject: [PATCH 018/227] feat(examples): add operations example

---
 src/Examples/OperationsExample/.gitignore     | 236 ++++++++++++++++++
 .../Controllers/OperationsController.cs       |  14 ++
 .../OperationsExample/Data/AppDbContext.cs    |  14 ++
 .../20170827234334_AddArticles.Designer.cs    |  33 +++
 .../Migrations/20170827234334_AddArticles.cs  |  32 +++
 .../Migrations/AppDbContextModelSnapshot.cs   |  32 +++
 .../OperationsExample/Models/Article.cs       |  10 +
 .../OperationsExample.csproj                  |  33 +++
 src/Examples/OperationsExample/Program.cs     |  26 ++
 src/Examples/OperationsExample/Startup.cs     |  66 +++++
 .../OperationsExample/appsettings.json        |  13 +
 11 files changed, 509 insertions(+)
 create mode 100644 src/Examples/OperationsExample/.gitignore
 create mode 100644 src/Examples/OperationsExample/Controllers/OperationsController.cs
 create mode 100644 src/Examples/OperationsExample/Data/AppDbContext.cs
 create mode 100755 src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs
 create mode 100755 src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs
 create mode 100755 src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs
 create mode 100644 src/Examples/OperationsExample/Models/Article.cs
 create mode 100644 src/Examples/OperationsExample/OperationsExample.csproj
 create mode 100644 src/Examples/OperationsExample/Program.cs
 create mode 100644 src/Examples/OperationsExample/Startup.cs
 create mode 100644 src/Examples/OperationsExample/appsettings.json

diff --git a/src/Examples/OperationsExample/.gitignore b/src/Examples/OperationsExample/.gitignore
new file mode 100644
index 0000000000..0f552f400b
--- /dev/null
+++ b/src/Examples/OperationsExample/.gitignore
@@ -0,0 +1,236 @@
+_data/
+
+## 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/src/Examples/OperationsExample/Controllers/OperationsController.cs b/src/Examples/OperationsExample/Controllers/OperationsController.cs
new file mode 100644
index 0000000000..d0ceaab71e
--- /dev/null
+++ b/src/Examples/OperationsExample/Controllers/OperationsController.cs
@@ -0,0 +1,14 @@
+using JsonApiDotNetCore.Controllers;
+using JsonApiDotNetCore.Services.Operations;
+using Microsoft.AspNetCore.Mvc;
+
+namespace OperationsExample.Controllers
+{
+    [Route("api/[controller]")]
+    public class OperationsController : JsonApiOperationsController
+    {
+        public OperationsController(IOperationsProcessor processor)
+            : base(processor)
+        { }
+    }
+}
diff --git a/src/Examples/OperationsExample/Data/AppDbContext.cs b/src/Examples/OperationsExample/Data/AppDbContext.cs
new file mode 100644
index 0000000000..d00bfe4765
--- /dev/null
+++ b/src/Examples/OperationsExample/Data/AppDbContext.cs
@@ -0,0 +1,14 @@
+using Microsoft.EntityFrameworkCore;
+using OperationsExample.Models;
+
+namespace OperationsExample.Data
+{
+    public class AppDbContext : DbContext
+    {
+        public AppDbContext(DbContextOptions<AppDbContext> options)
+        : base(options)
+        { }
+
+        public DbSet<Article> Articles { get; set; }
+    }
+}
diff --git a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs b/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs
new file mode 100755
index 0000000000..10f16d49cd
--- /dev/null
+++ b/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs
@@ -0,0 +1,33 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using OperationsExample.Data;
+
+namespace OperationsExample.Migrations
+{
+    [DbContext(typeof(AppDbContext))]
+    [Migration("20170827234334_AddArticles")]
+    partial class AddArticles
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+            modelBuilder
+                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
+                .HasAnnotation("ProductVersion", "1.1.2");
+
+            modelBuilder.Entity("OperationsExample.Models.Article", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Articles");
+                });
+        }
+    }
+}
diff --git a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs b/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs
new file mode 100755
index 0000000000..308e6f78f5
--- /dev/null
+++ b/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Metadata;
+
+namespace OperationsExample.Migrations
+{
+    public partial class AddArticles : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.CreateTable(
+                name: "Articles",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
+                    Name = table.Column<string>(nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Articles", x => x.Id);
+                });
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "Articles");
+        }
+    }
+}
diff --git a/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs b/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs
new file mode 100755
index 0000000000..547bbbf2cf
--- /dev/null
+++ b/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs
@@ -0,0 +1,32 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using OperationsExample.Data;
+
+namespace OperationsExample.Migrations
+{
+    [DbContext(typeof(AppDbContext))]
+    partial class AppDbContextModelSnapshot : ModelSnapshot
+    {
+        protected override void BuildModel(ModelBuilder modelBuilder)
+        {
+            modelBuilder
+                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
+                .HasAnnotation("ProductVersion", "1.1.2");
+
+            modelBuilder.Entity("OperationsExample.Models.Article", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Articles");
+                });
+        }
+    }
+}
diff --git a/src/Examples/OperationsExample/Models/Article.cs b/src/Examples/OperationsExample/Models/Article.cs
new file mode 100644
index 0000000000..fc4b5d6647
--- /dev/null
+++ b/src/Examples/OperationsExample/Models/Article.cs
@@ -0,0 +1,10 @@
+using JsonApiDotNetCore.Models;
+
+namespace OperationsExample.Models
+{
+    public class Article : Identifiable
+    {
+        [Attr("name")]
+        public string Name { get; set; }
+    }
+}
diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj
new file mode 100644
index 0000000000..e033989925
--- /dev/null
+++ b/src/Examples/OperationsExample/OperationsExample.csproj
@@ -0,0 +1,33 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp1.0</TargetFramework>
+    <PreserveCompilationContext>true</PreserveCompilationContext>
+    <AssemblyName>OperationsExample</AssemblyName>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="../../JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.2" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.2" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="1.1.2" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.2" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
+    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.1" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.2" />
+    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="1.1.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
+  </ItemGroup>
+
+</Project>
diff --git a/src/Examples/OperationsExample/Program.cs b/src/Examples/OperationsExample/Program.cs
new file mode 100644
index 0000000000..b528f47d15
--- /dev/null
+++ b/src/Examples/OperationsExample/Program.cs
@@ -0,0 +1,26 @@
+using System.IO;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+
+namespace OperationsExample
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            var config = new ConfigurationBuilder()
+                .AddCommandLine(args)
+                .AddEnvironmentVariables(prefix: "ASPNETCORE_")
+                .Build();
+
+            var host = new WebHostBuilder()
+                .UseConfiguration(config)
+                .UseKestrel()
+                .UseContentRoot(Directory.GetCurrentDirectory())
+                .UseStartup<Startup>()
+                .Build();
+
+            host.Run();
+        }
+    }
+}
diff --git a/src/Examples/OperationsExample/Startup.cs b/src/Examples/OperationsExample/Startup.cs
new file mode 100644
index 0000000000..40e9f5295a
--- /dev/null
+++ b/src/Examples/OperationsExample/Startup.cs
@@ -0,0 +1,66 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.EntityFrameworkCore;
+using JsonApiDotNetCore.Extensions;
+using System;
+using OperationsExample.Data;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Formatters;
+
+namespace OperationsExample
+{
+    public class Startup
+    {
+        public readonly IConfiguration Config;
+
+        public Startup(IHostingEnvironment env)
+        {
+            var builder = new ConfigurationBuilder()
+                .SetBasePath(env.ContentRootPath)
+                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
+                .AddEnvironmentVariables();
+
+            Config = builder.Build();
+        }
+
+        public virtual IServiceProvider ConfigureServices(IServiceCollection services)
+        {
+            var loggerFactory = new LoggerFactory();
+            loggerFactory
+              .AddConsole(LogLevel.Trace);
+            services.AddSingleton<ILoggerFactory>(loggerFactory);
+
+            services.AddDbContext<AppDbContext>(options =>
+            {
+                options.UseNpgsql(GetDbConnectionString());
+            }, ServiceLifetime  .Transient);
+
+            services.AddJsonApi<AppDbContext>(opt => opt.EnableExtension(JsonApiExtension.Operations));
+
+            services.AddMvc().AddMvcOptions(options => {
+                    options.InputFormatters.Clear();
+                    options.InputFormatters.Insert(0, new JsonApiOperationsInputFormatter());
+                });
+
+            return services.BuildServiceProvider();
+        }
+
+        public virtual void Configure(
+            IApplicationBuilder app,
+            IHostingEnvironment env,
+            ILoggerFactory loggerFactory,
+            AppDbContext context)
+        {
+            context.Database.EnsureCreated();
+
+            loggerFactory.AddConsole(Config.GetSection("Logging"));
+            loggerFactory.AddDebug();
+            app.UseJsonApi();
+        }
+
+        public string GetDbConnectionString() => Config["Data:DefaultConnection"];
+    }
+}
\ No newline at end of file
diff --git a/src/Examples/OperationsExample/appsettings.json b/src/Examples/OperationsExample/appsettings.json
new file mode 100644
index 0000000000..c1061281cc
--- /dev/null
+++ b/src/Examples/OperationsExample/appsettings.json
@@ -0,0 +1,13 @@
+{
+  "Data": {
+    "DefaultConnection": "Host=localhost;Port=5432;Database=OperationsExample;User ID=postgres;Password=password"
+  },
+  "Logging": {
+    "IncludeScopes": false,
+    "LogLevel": {
+      "Default": "Trace",
+      "System": "Trace",
+      "Microsoft": "Trace"
+    }
+  }
+}

From 34e68297ab5bbf831d41ca74ed2a2a3969df6dc2 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 12 Sep 2017 06:30:16 -0500
Subject: [PATCH 019/227] fix(controller): use HTTP PATCH

---
 .vscode/launch.json                                    | 10 ++++++++++
 .../Controllers/OperationsController.cs                |  2 +-
 .../Controllers/JsonApiOperationsController.cs         |  2 +-
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/.vscode/launch.json b/.vscode/launch.json
index b26b008078..1da452f8e1 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,6 +1,16 @@
 {
     "version": "0.2.0",
     "configurations": [
+        {
+            "name": "OperationsExample",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build",
+            "program": "${workspaceRoot}/src/Examples/OperationsExample/bin/Debug/netcoreapp1.0/OperationsExample.dll",
+            "args": [],
+            "cwd": "${workspaceRoot}/src/Examples/OperationsExample",
+            "stopAtEntry": false
+        },
         {
             "name": ".NET Core Attach",
             "type": "coreclr",
diff --git a/src/Examples/OperationsExample/Controllers/OperationsController.cs b/src/Examples/OperationsExample/Controllers/OperationsController.cs
index d0ceaab71e..6e56791f9c 100644
--- a/src/Examples/OperationsExample/Controllers/OperationsController.cs
+++ b/src/Examples/OperationsExample/Controllers/OperationsController.cs
@@ -4,7 +4,7 @@
 
 namespace OperationsExample.Controllers
 {
-    [Route("api/[controller]")]
+    [Route("api/bulk")]
     public class OperationsController : JsonApiOperationsController
     {
         public OperationsController(IOperationsProcessor processor)
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
index 40ac76fea3..639468450d 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
@@ -14,7 +14,7 @@ public JsonApiOperationsController(IOperationsProcessor operationsProcessor)
             _operationsProcessor = operationsProcessor;
         }
 
-        [HttpPost("bulk")]
+        [HttpPatch]
         public async Task<IActionResult> PatchAsync(OperationsDocument doc)
         {
             var results = await _operationsProcessor.ProcessAsync(doc.Operations);

From e476e25b7e19d09f66f8f7f26dc6684de82bf303 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 13 Sep 2017 07:25:04 -0500
Subject: [PATCH 020/227] fix(inputFormatters): needed FromBody param attribute

---
 .vscode/tasks.json                            | 38 +++++++++----------
 src/Examples/OperationsExample/Startup.cs     |  8 +---
 .../JsonApiOperationsController.cs            |  2 +-
 .../IServiceCollectionExtensions.cs           |  5 ++-
 .../Formatters/JsonApiInputFormatter.cs       |  5 +--
 .../JsonApiOperationsInputFormatter.cs        | 18 ++-------
 6 files changed, 29 insertions(+), 47 deletions(-)

diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 725d8335be..3906009211 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,20 +1,20 @@
 {
-    // See https://go.microsoft.com/fwlink/?LinkId=733558
-    // for the documentation about the tasks.json format
-    "version": "0.1.0",
-    "command": "dotnet",
-    "isShellCommand": true,
-    "args": [],
-    "options": {
-      "cwd": "${workspaceRoot}/src/Examples/JsonApiDotNetCoreExample"
-    },
-    "tasks": [
-        {
-            "taskName": "build",
-            "args": [ ],
-            "isBuildCommand": true,
-            "showOutput": "silent",
-            "problemMatcher": "$msCompile"
-        }
-    ]
-}
\ No newline at end of file
+  // See https://go.microsoft.com/fwlink/?LinkId=733558
+  // for the documentation about the tasks.json format
+  "version": "0.1.0",
+  "command": "dotnet",
+  "isShellCommand": true,
+  "args": [],
+  "options": {
+    "cwd": "${workspaceRoot}"
+  },
+  "tasks": [
+    {
+      "taskName": "build",
+      "args": [],
+      "isBuildCommand": true,
+      "showOutput": "silent",
+      "problemMatcher": "$msCompile"
+    }
+  ]
+}
diff --git a/src/Examples/OperationsExample/Startup.cs b/src/Examples/OperationsExample/Startup.cs
index 40e9f5295a..1ffedf9116 100644
--- a/src/Examples/OperationsExample/Startup.cs
+++ b/src/Examples/OperationsExample/Startup.cs
@@ -8,7 +8,6 @@
 using System;
 using OperationsExample.Data;
 using JsonApiDotNetCore.Models;
-using JsonApiDotNetCore.Formatters;
 
 namespace OperationsExample
 {
@@ -36,15 +35,10 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
             services.AddDbContext<AppDbContext>(options =>
             {
                 options.UseNpgsql(GetDbConnectionString());
-            }, ServiceLifetime  .Transient);
+            }, ServiceLifetime.Transient);
 
             services.AddJsonApi<AppDbContext>(opt => opt.EnableExtension(JsonApiExtension.Operations));
 
-            services.AddMvc().AddMvcOptions(options => {
-                    options.InputFormatters.Clear();
-                    options.InputFormatters.Insert(0, new JsonApiOperationsInputFormatter());
-                });
-
             return services.BuildServiceProvider();
         }
 
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
index 639468450d..3990f7b85d 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
@@ -15,7 +15,7 @@ public JsonApiOperationsController(IOperationsProcessor operationsProcessor)
         }
 
         [HttpPatch]
-        public async Task<IActionResult> PatchAsync(OperationsDocument doc)
+        public async Task<IActionResult> PatchAsync([FromBody] OperationsDocument doc)
         {
             var results = await _operationsProcessor.ProcessAsync(doc.Operations);
             return Ok(results);
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 6cd84d397c..12e86d09ea 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -112,6 +112,7 @@ public static void AddJsonApiInternals(
             services.AddScoped<IJsonApiWriter, JsonApiWriter>();
             services.AddScoped<IJsonApiDeSerializer, JsonApiDeSerializer>();
             services.AddScoped<IJsonApiReader, JsonApiReader>();
+            services.AddScoped<IJsonApiOperationsReader, JsonApiOperationsReader>();
             services.AddScoped<IGenericProcessorFactory, GenericProcessorFactory>();
             services.AddScoped(typeof(GenericProcessor<>));
             services.AddScoped<IQueryAccessor, QueryAccessor>();
@@ -128,11 +129,11 @@ private static void AddOperationServices(IServiceCollection services)
 
         public static void SerializeAsJsonApi(this MvcOptions options, JsonApiOptions jsonApiOptions)
         {
+            options.InputFormatters.Insert(0, new JsonApiInputFormatter());
+
             if (jsonApiOptions.EnabledExtensions.Contains(JsonApiExtension.Operations))
                 options.InputFormatters.Insert(0, new JsonApiOperationsInputFormatter());
 
-            options.InputFormatters.Insert(0, new JsonApiInputFormatter());
-
             options.OutputFormatters.Insert(0, new JsonApiOutputFormatter());
 
             options.Conventions.Insert(0, new DasherizedRoutingConvention(jsonApiOptions.Namespace));
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
index f5b822fd62..b7f5ae7f76 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
@@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Formatters
     public class JsonApiInputFormatter : IInputFormatter
     {
         public bool CanRead(InputFormatterContext context)
-        {            
+        {
             if (context == null)
                 throw new ArgumentNullException(nameof(context));
 
@@ -16,14 +16,11 @@ public bool CanRead(InputFormatterContext context)
 
             var canRead = contentTypeString == "application/vnd.api+json";
 
-            Console.WriteLine($">>> JsonApiInputFormatter Can Read {canRead}");
-
             return canRead;
         }
 
         public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
         {
-            Console.WriteLine($">>> JsonApiInputFormatter ReadAsync");
             var reader = context.HttpContext.RequestServices.GetService<IJsonApiReader>();
             return await reader.ReadAsync(context);
         }
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
index 0f83c1f031..de5ed86bf1 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
@@ -1,25 +1,16 @@
 using System;
-using System.Text;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Mvc.Formatters;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Primitives;
-using Microsoft.Net.Http.Headers;
 
 namespace JsonApiDotNetCore.Formatters
 {
-    public class JsonApiOperationsInputFormatter : TextInputFormatter
+    public class JsonApiOperationsInputFormatter : IInputFormatter
     {
         const string PROFILE_EXTENSION = "<http://example.org/profiles/myjsonstuff>; rel=\"profile\"";
 
-        public JsonApiOperationsInputFormatter()
-        {
-            SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/vnd.api+json"));
-            SupportedEncodings.Add(Encoding.UTF8);
-            SupportedEncodings.Add(Encoding.Unicode);
-        }
-
-        public override bool CanRead(InputFormatterContext context)
+        public bool CanRead(InputFormatterContext context)
         {
             if (context == null)
                 throw new ArgumentNullException(nameof(context));
@@ -31,13 +22,12 @@ public override bool CanRead(InputFormatterContext context)
                 context.HttpContext.Request.Headers.TryGetValue("Link", out StringValues profileExtension) &&
                 profileExtension == PROFILE_EXTENSION
             );
-            Console.WriteLine($">>> JsonApiOperationsInputFormatter Can Read {canRead}");
+
             return canRead;
         }
 
-        public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
+        public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
         {
-            Console.WriteLine($">>> JsonApiOperationsInputFormatter ReadAsync");
             var reader = context.HttpContext.RequestServices.GetService<IJsonApiOperationsReader>();
             return await reader.ReadAsync(context);
         }

From bc18fe92511e696beaa4f34fc969392ccffcc46b Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 14 Sep 2017 21:54:11 -0500
Subject: [PATCH 021/227] chore(*): replace Any with Count

---
 docs/Usage.md                                          |  2 +-
 src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs  |  2 +-
 .../Extensions/IQueryableExtensions.cs                 | 10 +++++-----
 src/JsonApiDotNetCore/Services/JsonApiContext.cs       |  2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/docs/Usage.md b/docs/Usage.md
index 33db2d787f..07ac168a21 100644
--- a/docs/Usage.md
+++ b/docs/Usage.md
@@ -117,7 +117,7 @@ public void Configure(
             AppDbContext context)
 {
     context.Database.EnsureCreated();
-    if(context.People.Any() == false) 
+    if(context.People.Count == 0) 
     {
         context.People.Add(new Person {
             Name = "John Doe"
diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index 66804abee5..742a32e305 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -62,7 +62,7 @@ public DefaultEntityRepository(
 
         public virtual IQueryable<TEntity> Get()
         {
-            if (_jsonApiContext.QuerySet?.Fields != null && _jsonApiContext.QuerySet.Fields.Any())
+            if (_jsonApiContext.QuerySet?.Fields != null && _jsonApiContext.QuerySet.Fields.Count > 0)
                 return _dbSet.Select(_jsonApiContext.QuerySet?.Fields);
 
             return _dbSet;
diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index c40d61b517..9713b6ddbf 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -13,15 +13,15 @@ public static class IQueryableExtensions
     {
         public static IOrderedQueryable<TSource> Sort<TSource>(this IQueryable<TSource> source, SortQuery sortQuery)
         {
-            return sortQuery.Direction == SortDirection.Descending 
-                ? source.OrderByDescending(sortQuery.SortedAttribute.InternalAttributeName) 
+            return sortQuery.Direction == SortDirection.Descending
+                ? source.OrderByDescending(sortQuery.SortedAttribute.InternalAttributeName)
                 : source.OrderBy(sortQuery.SortedAttribute.InternalAttributeName);
         }
 
         public static IOrderedQueryable<TSource> Sort<TSource>(this IOrderedQueryable<TSource> source, SortQuery sortQuery)
         {
-            return sortQuery.Direction == SortDirection.Descending 
-                ? source.ThenByDescending(sortQuery.SortedAttribute.InternalAttributeName) 
+            return sortQuery.Direction == SortDirection.Descending
+                ? source.ThenByDescending(sortQuery.SortedAttribute.InternalAttributeName)
                 : source.ThenBy(sortQuery.SortedAttribute.InternalAttributeName);
         }
 
@@ -179,7 +179,7 @@ private static Expression GetFilterExpressionLambda(Expression left, Expression
 
         public static IQueryable<TSource> Select<TSource>(this IQueryable<TSource> source, List<string> columns)
         {
-            if (columns == null || columns.Any() == false)
+            if (columns == null || columns.Count == 0)
                 return source;
 
             var sourceType = source.ElementType;
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index a93d76acdc..85978c66f6 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -66,7 +66,7 @@ public IJsonApiContext ApplyContext<T>(object controller)
             var context = _httpContextAccessor.HttpContext;
             var path = context.Request.Path.Value.Split('/');
 
-            if (context.Request.Query.Any())
+            if (context.Request.Query.Count > 0)
             {
                 QuerySet = _queryParser.Parse(context.Request.Query);
                 IncludedRelationships = QuerySet.IncludedRelationships;

From 6c1937f9d658d2e51987e1013771a57b6da69e1d Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 14 Sep 2017 23:47:49 -0500
Subject: [PATCH 022/227] fix(CreateOpProcessor): issues around service
 location

also cleans up some styling
---
 .../Builders/ContextGraphBuilder.cs           | 44 +++++++++++--------
 .../Data/DefaultEntityRepository.cs           |  2 +-
 .../IServiceCollectionExtensions.cs           |  6 +++
 .../Internal/Generics/GenericProcessor.cs     | 13 +++++-
 .../Generics/GenericProcessorFactory.cs       | 37 ++++++++++++++--
 .../Internal/Generics/IGenericProcessor.cs    | 12 -----
 .../Generics/IGenericProcessorFactory.cs      | 15 -------
 src/JsonApiDotNetCore/Models/DocumentBase.cs  | 22 ++--------
 src/JsonApiDotNetCore/Models/DocumentData.cs  |  2 +-
 .../Models/Operations/Operation.cs            | 28 ++++++++----
 .../Serialization/JsonApiDeSerializer.cs      |  2 +-
 .../Services/Operations/IOpProcessor.cs       |  5 ---
 .../Operations/OperationProcessorResolver.cs  |  9 ++--
 .../Operations/OperationsProcessor.cs         |  8 ++--
 .../Processors/CreateOpProcessor.cs           | 17 +++++--
 15 files changed, 126 insertions(+), 96 deletions(-)
 delete mode 100644 src/JsonApiDotNetCore/Internal/Generics/IGenericProcessor.cs
 delete mode 100644 src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs

diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index efbc0535e1..e35cc916d2 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -35,20 +35,22 @@ public IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeNam
         {
             var entityType = typeof(TResource);
 
-            VerifyEntityIsNotAlreadyDefined(entityType);
+            AssertEntityIsNotAlreadyDefined(entityType);
 
-            _entities.Add(new ContextEntity
-            {
-                EntityName = pluralizedTypeName,
-                EntityType = entityType,
-                IdentityType = typeof(TId),
-                Attributes = GetAttributes(entityType),
-                Relationships = GetRelationships(entityType)
-            });
+            _entities.Add(GetEntity(pluralizedTypeName, entityType, typeof(TId)));
 
             return this;
         }
 
+        private ContextEntity GetEntity(string pluralizedTypeName, Type entityType, Type idType) => new ContextEntity
+        {
+            EntityName = pluralizedTypeName,
+            EntityType = entityType,
+            IdentityType = idType,
+            Attributes = GetAttributes(entityType),
+            Relationships = GetRelationships(entityType)
+        };
+
         private Link GetLinkFlags(Type entityType)
         {
             var attribute = (LinksAttribute)entityType.GetTypeInfo().GetCustomAttribute(typeof(LinksAttribute));
@@ -116,15 +118,9 @@ public IContextGraphBuilder AddDbContext<T>() where T : DbContext
                 {
                     var entityType = dbSetType.GetGenericArguments()[0];
 
-                    VerifyEntityIsNotAlreadyDefined(entityType);
+                    AssertEntityIsNotAlreadyDefined(entityType);
 
-                    _entities.Add(new ContextEntity
-                    {
-                        EntityName = GetResourceName(property),
-                        EntityType = entityType,
-                        Attributes = GetAttributes(entityType),
-                        Relationships = GetRelationships(entityType)
-                    });
+                    _entities.Add(GetEntity(GetResourceName(property), entityType, GetIdType(entityType)));
                 }
             }
 
@@ -140,7 +136,19 @@ private string GetResourceName(PropertyInfo property)
             return ((ResourceAttribute)resourceAttribute).ResourceName;
         }
 
-        private void VerifyEntityIsNotAlreadyDefined(Type entityType)
+        private Type GetIdType(Type resourceType)
+        {
+            var interfaces = resourceType.GetInterfaces();
+            foreach (var type in interfaces)
+            {
+                if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(IIdentifiable<>))
+                    return type.GetGenericArguments()[0];
+            }
+
+            throw new ArgumentException("Type does not implement 'IIdentifiable<TId>'", nameof(resourceType));
+        }
+
+        private void AssertEntityIsNotAlreadyDefined(Type entityType)
         {
             if (_entities.Any(e => e.EntityType == entityType))
                 throw new InvalidOperationException($"Cannot add entity type {entityType} to context graph, there is already an entity of that type configured.");
diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index 742a32e305..e8aefb5ca9 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -137,7 +137,7 @@ public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
 
         public async Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds)
         {
-            var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(relationship.Type);
+            var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(typeof(GenericProcessor<>), relationship.Type);
             await genericProcessor.UpdateRelationshipsAsync(parent, relationship, relationshipIds);
         }
 
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 12e86d09ea..ab297252f9 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -10,6 +10,7 @@
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
 using JsonApiDotNetCore.Services.Operations;
+using JsonApiDotNetCore.Services.Operations.Processors;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.EntityFrameworkCore;
@@ -99,6 +100,8 @@ public static void AddJsonApiInternals(
             services.AddScoped<IDbContextResolver, DbContextResolver>();
             services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
             services.AddScoped(typeof(IEntityRepository<,>), typeof(DefaultEntityRepository<,>));
+            services.AddScoped(typeof(ICreateService<>), typeof(EntityResourceService<>));
+            services.AddScoped(typeof(ICreateService<,>), typeof(EntityResourceService<,>));
             services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IResourceService<,>), typeof(EntityResourceService<,>));
             services.AddSingleton<JsonApiOptions>(jsonApiOptions);
@@ -115,6 +118,7 @@ public static void AddJsonApiInternals(
             services.AddScoped<IJsonApiOperationsReader, JsonApiOperationsReader>();
             services.AddScoped<IGenericProcessorFactory, GenericProcessorFactory>();
             services.AddScoped(typeof(GenericProcessor<>));
+            services.AddScoped(typeof(GenericProcessor<,>));
             services.AddScoped<IQueryAccessor, QueryAccessor>();
             services.AddScoped<IQueryParser, QueryParser>();
             services.AddScoped<IControllerContext, Services.ControllerContext>();
@@ -123,6 +127,8 @@ public static void AddJsonApiInternals(
         private static void AddOperationServices(IServiceCollection services)
         {
             services.AddScoped<IOperationsProcessor, OperationsProcessor>();
+            services.AddScoped(typeof(ICreateOpProcessor<>), typeof(CreateOpProcessor<>));
+            services.AddScoped(typeof(ICreateOpProcessor<,>), typeof(CreateOpProcessor<,>));
             services.AddSingleton<IOperationProcessorResolver, OperationProcessorResolver>();
             services.AddSingleton<IGenericProcessorFactory, GenericProcessorFactory>();
         }
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
index ce76b47dae..74bc551ece 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
@@ -7,7 +7,18 @@
 
 namespace JsonApiDotNetCore.Internal.Generics
 {
-    public class GenericProcessor<T> : IGenericProcessor where T : class, IIdentifiable
+    public interface IGenericProcessor
+    {
+        Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
+        void SetRelationships(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
+    }
+
+    public class GenericProcessor<T> : GenericProcessor<T, int> where T : class, IIdentifiable<int>
+    {
+        public GenericProcessor(DbContext context) : base(context) { }
+    }
+
+    public class GenericProcessor<T, TId> : IGenericProcessor where T : class, IIdentifiable<TId>
     {
         private readonly DbContext _context;
         public GenericProcessor(DbContext context)
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
index 0918da40d1..3f88010e0a 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
@@ -2,6 +2,30 @@
 
 namespace JsonApiDotNetCore.Internal.Generics
 {
+    /// <summary>
+    /// Used to generate a generic operations processor when the types
+    /// are not known until runtime. The typical use case would be for
+    /// accessing relationship data or resolving operations processors.
+    /// </summary>
+    public interface IGenericProcessorFactory
+    {
+        /// <summary>
+        /// Constructs the generic type and locates the service, then casts to TInterface
+        /// </summary>
+        /// <example>
+        ///     GetProcessor&lt;IGenericProcessor&gt;(typeof(GenericProcessor&lt;&gt;), typeof(TResource));
+        /// </example>
+        TInterface GetProcessor<TInterface>(Type openGenericType, Type resourceType);
+
+        /// <summary>
+        /// Constructs the generic type and locates the service, then casts to TInterface
+        /// </summary>
+        /// <example>
+        ///     GetProcessor&lt;IGenericProcessor&gt;(typeof(GenericProcessor&lt;,&gt;), typeof(TResource), typeof(TId));
+        /// </example>
+        TInterface GetProcessor<TInterface>(Type openGenericType, Type resourceType, Type keyType);
+    }
+
     public class GenericProcessorFactory : IGenericProcessorFactory
     {
         private readonly IServiceProvider _serviceProvider;
@@ -11,10 +35,17 @@ public GenericProcessorFactory(IServiceProvider serviceProvider)
             _serviceProvider = serviceProvider;
         }
 
-        public TInterface GetProcessor<TInterface>(Type[] types)
+        public TInterface GetProcessor<TInterface>(Type openGenericType, Type resourceType)
+            => _getProcessor<TInterface>(openGenericType, resourceType);
+
+        public TInterface GetProcessor<TInterface>(Type openGenericType, Type resourceType, Type keyType)
+            => _getProcessor<TInterface>(openGenericType, resourceType, keyType);
+
+        private TInterface _getProcessor<TInterface>(Type openGenericType, params Type[] types)
         {
-            var processorType = typeof(GenericProcessor<>).MakeGenericType(types);
-            return (TInterface)_serviceProvider.GetService(processorType);
+            var concreteType = openGenericType.MakeGenericType(types);
+
+            return (TInterface)_serviceProvider.GetService(concreteType);
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessor.cs b/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessor.cs
deleted file mode 100644
index d05e47cb6c..0000000000
--- a/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessor.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using JsonApiDotNetCore.Models;
-
-namespace JsonApiDotNetCore.Internal.Generics
-{
-    public interface IGenericProcessor
-    {
-        Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
-        void SetRelationships(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
-    }
-}
diff --git a/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs
deleted file mode 100644
index 39df292e14..0000000000
--- a/src/JsonApiDotNetCore/Internal/Generics/IGenericProcessorFactory.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-
-namespace JsonApiDotNetCore.Internal.Generics
-{
-    /// <summary>
-    /// Used to generate a generic operations processor when the types
-    /// are not know until runtime. The typical use case would be for
-    /// accessing relationship data.be for
-    /// accessing relationship data.
-    /// </summary>
-    public interface IGenericProcessorFactory
-    {
-        TInterface GetProcessor<TInterface>(params Type[] types);
-    }
-}
diff --git a/src/JsonApiDotNetCore/Models/DocumentBase.cs b/src/JsonApiDotNetCore/Models/DocumentBase.cs
index 1cb31595ec..eb38f9582d 100644
--- a/src/JsonApiDotNetCore/Models/DocumentBase.cs
+++ b/src/JsonApiDotNetCore/Models/DocumentBase.cs
@@ -5,29 +5,13 @@ namespace JsonApiDotNetCore.Models
 {
     public class DocumentBase
     {
-        [JsonProperty("links")]
+        [JsonProperty("links", NullValueHandling = NullValueHandling.Ignore)]
         public RootLinks Links { get; set; }
 
-        [JsonProperty("included")]
+        [JsonProperty("included", NullValueHandling = NullValueHandling.Ignore)]
         public List<DocumentData> Included { get; set; }
 
-        [JsonProperty("meta")]
+        [JsonProperty("meta", NullValueHandling = NullValueHandling.Ignore)]
         public Dictionary<string, object> Meta { get; set; }
-
-        // http://www.newtonsoft.com/json/help/html/ConditionalProperties.htm
-        public bool ShouldSerializeIncluded()
-        {
-            return (Included != null);
-        }
-
-        public bool ShouldSerializeMeta()
-        {
-            return (Meta != null);
-        }
-
-        public bool ShouldSerializeLinks()
-        {
-            return (Links != null);
-        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/DocumentData.cs b/src/JsonApiDotNetCore/Models/DocumentData.cs
index f4a3c137ae..7b5bdadd5b 100644
--- a/src/JsonApiDotNetCore/Models/DocumentData.cs
+++ b/src/JsonApiDotNetCore/Models/DocumentData.cs
@@ -14,7 +14,7 @@ public class DocumentData
         [JsonProperty("attributes")]
         public Dictionary<string, object> Attributes { get; set; }
 
-        [JsonProperty("relationships")]
+        [JsonProperty("relationships", NullValueHandling = NullValueHandling.Ignore)]
         public Dictionary<string, RelationshipData> Relationships { get; set; }
     }
 }
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Models/Operations/Operation.cs b/src/JsonApiDotNetCore/Models/Operations/Operation.cs
index 1493142b9f..38c544eabc 100644
--- a/src/JsonApiDotNetCore/Models/Operations/Operation.cs
+++ b/src/JsonApiDotNetCore/Models/Operations/Operation.cs
@@ -1,18 +1,19 @@
 using System.Collections.Generic;
 using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
 using Newtonsoft.Json.Linq;
 
 namespace JsonApiDotNetCore.Models.Operations
 {
     public class Operation : DocumentBase
     {
-        [JsonProperty("op")]
+        [JsonProperty("op"), JsonConverter(typeof(StringEnumConverter))]
         public OperationCode Op { get; set; }
 
-        [JsonProperty("ref")]
+        [JsonProperty("ref", NullValueHandling = NullValueHandling.Ignore)]
         public ResourceReference Ref { get; set; }
 
-        [JsonProperty("params")]
+        [JsonProperty("params", NullValueHandling = NullValueHandling.Ignore)]
         public Params Params { get; set; }
 
         [JsonProperty("data")]
@@ -28,32 +29,41 @@ public object Data
 
         private void SetData(object data)
         {
-            if (data is JArray jArray) {
+            if (data is JArray jArray)
+            {
                 DataIsList = true;
                 DataList = jArray.ToObject<List<DocumentData>>();
             }
-            else if (data is List<DocumentData> dataList) {
+            else if (data is List<DocumentData> dataList)
+            {
                 DataIsList = true;
                 DataList = dataList;
             }
-            else if (data is JObject jObject) {
+            else if (data is JObject jObject)
+            {
                 DataObject = jObject.ToObject<DocumentData>();
             }
-            else if (data is DocumentData dataObject) {
+            else if (data is DocumentData dataObject)
+            {
                 DataObject = dataObject;
             }
         }
 
+        [JsonIgnore]
         public bool DataIsList { get; private set; }
+
+        [JsonIgnore]
         public List<DocumentData> DataList { get; private set; }
+
+        [JsonIgnore]
         public DocumentData DataObject { get; private set; }
 
         public string GetResourceTypeName()
         {
-            if(Ref != null)
+            if (Ref != null)
                 return Ref.Type?.ToString();
 
-            if(DataIsList)
+            if (DataIsList)
                 return DataList[0].Type?.ToString();
 
             return DataObject.Type?.ToString();
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index a5168f6185..05394fe551 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -210,7 +210,7 @@ private object SetHasManyRelationship(object entity,
 
                 if (data == null) return entity;
 
-                var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(attr.Type);
+                var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(typeof(GenericProcessor<>), attr.Type);
                 var ids = relationshipData.ManyData.Select(r => r["id"].ToString());
                 genericProcessor.SetRelationships(entity, attr, ids);
             }
diff --git a/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
index 67cd0896ec..0a2d30397c 100644
--- a/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/IOpProcessor.cs
@@ -1,5 +1,4 @@
 using System.Threading.Tasks;
-using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 
 namespace JsonApiDotNetCore.Services.Operations
@@ -8,8 +7,4 @@ public interface IOpProcessor
     {
         Task<Operation> ProcessAsync(Operation operation);
     }
-
-    public interface IOpProcessor<T, TId> : IOpProcessor 
-        where T : class, IIdentifiable<TId>
-    { }
 }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
index b56eb11bd6..64261af1c7 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -1,6 +1,7 @@
 using System.Collections.Concurrent;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Services.Operations.Processors;
 
 namespace JsonApiDotNetCore.Services.Operations
 {
@@ -33,10 +34,12 @@ public IOpProcessor LocateCreateService(Operation operation)
                 return cachedProcessor;
 
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
-            var processor = _processorFactory.GetProcessor<IOpProcessor>(contextEntity.EntityType, contextEntity.IdentityType);
-            
+            var processor = _processorFactory.GetProcessor<IOpProcessor>(
+                typeof(ICreateOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
+            );
+
             _cachedProcessors[resource] = processor;
-            
+
             return processor;
         }
     }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index 9449564f22..75e013c8c8 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -18,12 +18,12 @@ public OperationsProcessor(IOperationProcessorResolver processorResolver)
         {
             _processorResolver = processorResolver;
         }
-        
+
         public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
         {
             var outputOps = new List<Operation>();
 
-            foreach(var op in inputOps)
+            foreach (var op in inputOps)
             {
                 // TODO: parse pointers:
                 // locate all objects within the document and replace them
@@ -33,8 +33,8 @@ public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
 
                 var processor = _processorResolver.LocateCreateService(op);
                 var resultOp = await processor.ProcessAsync(op);
-                
-                if(resultOp != null)
+
+                if (resultOp != null)
                     outputOps.Add(resultOp);
             }
 
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
index 8ef9298027..251b81a5d6 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
@@ -7,6 +7,14 @@
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
+    public interface ICreateOpProcessor<T> : IOpProcessor
+        where T : class, IIdentifiable<int>
+    { }
+
+    public interface ICreateOpProcessor<T, TId> : IOpProcessor
+        where T : class, IIdentifiable<TId>
+    { }
+
     public class CreateOpProcessor<T> : CreateOpProcessor<T, int>
         where T : class, IIdentifiable<int>
     {
@@ -19,7 +27,7 @@ IContextGraph contextGraph
         { }
     }
 
-    public class CreateOpProcessor<T, TId> : IOpProcessor<T, TId>
+    public class CreateOpProcessor<T, TId> : ICreateOpProcessor<T, TId>
          where T : class, IIdentifiable<TId>
     {
         private readonly ICreateService<T, TId> _service;
@@ -44,12 +52,13 @@ public async Task<Operation> ProcessAsync(Operation operation)
             var model = (T)_deSerializer.DocumentToObject(operation.DataObject);
             var result = await _service.CreateAsync(model);
 
-            var operationResult = new Operation {
+            var operationResult = new Operation
+            {
                 Op = OperationCode.add
             };
-            
+
             operationResult.Data = _documentBuilder.GetData(
-                _contextGraph.GetContextEntity(operation.GetResourceTypeName()), 
+                _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
                 result);
 
             return operationResult;

From 8723bbe3c95279a0a4f7d699faf4b0f99753bdac Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 14 Sep 2017 23:48:44 -0500
Subject: [PATCH 023/227] fix(DocumentBuilder): duplicate included entities

use string.Equals over reference equality check
---
 .../Builders/DocumentBuilder.cs               | 43 ++++++++++---------
 1 file changed, 23 insertions(+), 20 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index c6439efbc8..775800434f 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -36,7 +36,7 @@ public Document Build(IIdentifiable entity)
                 Meta = GetMeta(entity)
             };
 
-            if(ShouldIncludePageLinks(contextEntity))
+            if (ShouldIncludePageLinks(contextEntity))
                 document.Links = _jsonApiContext.PageManager.GetPageLinks(new LinkBuilder(_jsonApiContext));
 
             document.Included = AppendIncludedObject(document.Included, contextEntity, entity);
@@ -59,7 +59,7 @@ public Documents Build(IEnumerable<IIdentifiable> entities)
                 Meta = GetMeta(enumeratedEntities.FirstOrDefault())
             };
 
-            if(ShouldIncludePageLinks(contextEntity))
+            if (ShouldIncludePageLinks(contextEntity))
                 documents.Links = _jsonApiContext.PageManager.GetPageLinks(new LinkBuilder(_jsonApiContext));
 
             foreach (var entity in enumeratedEntities)
@@ -74,20 +74,20 @@ public Documents Build(IEnumerable<IIdentifiable> entities)
         private Dictionary<string, object> GetMeta(IIdentifiable entity)
         {
             if (entity == null) return null;
-            
+
             var builder = _jsonApiContext.MetaBuilder;
 
-            if(entity is IHasMeta metaEntity)
+            if (entity is IHasMeta metaEntity)
                 builder.Add(metaEntity.GetMeta(_jsonApiContext));
 
-            if(_jsonApiContext.Options.IncludeTotalRecordCount)
+            if (_jsonApiContext.Options.IncludeTotalRecordCount)
                 builder.Add("total-records", _jsonApiContext.PageManager.TotalRecords);
-            
-            if(_requestMeta != null)
+
+            if (_requestMeta != null)
                 builder.Add(_requestMeta.GetMeta());
 
             var meta = builder.Build();
-            if(meta.Count > 0) return meta;
+            if (meta.Count > 0) return meta;
             return null;
         }
 
@@ -119,7 +119,7 @@ public DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
 
             contextEntity.Attributes.ForEach(attr =>
             {
-                if(ShouldIncludeAttribute(attr))
+                if (ShouldIncludeAttribute(attr))
                     data.Attributes.Add(attr.PublicAttributeName, attr.GetValue(entity));
             });
 
@@ -131,8 +131,8 @@ public DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
 
         private bool ShouldIncludeAttribute(AttrAttribute attr)
         {
-            return (_jsonApiContext.QuerySet == null 
-                || _jsonApiContext.QuerySet.Fields.Count == 0 
+            return (_jsonApiContext.QuerySet == null
+                || _jsonApiContext.QuerySet.Fields.Count == 0
                 || _jsonApiContext.QuerySet.Fields.Contains(attr.InternalAttributeName));
         }
 
@@ -145,13 +145,13 @@ private void AddRelationships(DocumentData data, ContextEntity contextEntity, II
             {
                 var relationshipData = new RelationshipData();
 
-                if(r.DocumentLinks.HasFlag(Link.None) == false)
+                if (r.DocumentLinks.HasFlag(Link.None) == false)
                 {
                     relationshipData.Links = new Links();
-                    if(r.DocumentLinks.HasFlag(Link.Self))
+                    if (r.DocumentLinks.HasFlag(Link.Self))
                         relationshipData.Links.Self = linkBuilder.GetSelfRelationLink(contextEntity.EntityName, entity.StringId, r.PublicRelationshipName);
-                    
-                    if(r.DocumentLinks.HasFlag(Link.Related))
+
+                    if (r.DocumentLinks.HasFlag(Link.Related))
                         relationshipData.Links.Related = linkBuilder.GetRelatedRelationLink(contextEntity.EntityName, entity.StringId, r.PublicRelationshipName);
                 }
 
@@ -160,7 +160,7 @@ private void AddRelationships(DocumentData data, ContextEntity contextEntity, II
                     var navigationEntity = _jsonApiContext.ContextGraph
                         .GetRelationship(entity, r.InternalRelationshipName);
 
-                    if(navigationEntity == null)
+                    if (navigationEntity == null)
                         relationshipData.SingleData = null;
                     else if (navigationEntity is IEnumerable)
                         relationshipData.ManyData = GetRelationships((IEnumerable<object>)navigationEntity);
@@ -194,19 +194,22 @@ private List<DocumentData> AddIncludedEntity(List<DocumentData> entities, IIdent
         {
             var includedEntity = GetIncludedEntity(entity);
 
-            if(entities == null)
+            if (entities == null)
                 entities = new List<DocumentData>();
 
-            if(includedEntity != null && !entities.Any(doc => doc.Id == includedEntity.Id && doc.Type == includedEntity.Type))
+            if (includedEntity != null && entities.Any(doc =>
+                string.Equals(doc.Id, includedEntity.Id) && string.Equals(doc.Type, includedEntity.Type)) == false)
+            {
                 entities.Add(includedEntity);
+            }
 
             return entities;
         }
 
         private DocumentData GetIncludedEntity(IIdentifiable entity)
         {
-            if(entity == null) return null;
-            
+            if (entity == null) return null;
+
             var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(entity.GetType());
 
             var data = GetData(contextEntity, entity);

From 017d37569a698bc5b918bd263b206a865b20e608 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 26 Sep 2017 21:48:24 -0500
Subject: [PATCH 024/227] test(add): integration tests add articles

---
 JsonApiDotnetCore.sln                         |  15 ++
 src/JsonApiDotNetCore/AssemblyInfo.cs         |   3 +
 .../JsonApiOperationsInputFormatter.cs        |   2 +-
 .../Formatters/JsonApiOperationsReader.cs     |   4 +-
 .../Serialization/JsonApiDeSerializer.cs      |   2 +
 test/OperationsExampleTests/.gitignore        | 234 ++++++++++++++++++
 test/OperationsExampleTests/Add/AddTests.cs   | 102 ++++++++
 .../Factories/ArticleFactory.cs               |  25 ++
 .../OperationsExampleTests.csproj             |  23 ++
 .../WebHostCollection.cs                      |  42 ++++
 test/OperationsExampleTests/appsettings.json  |  13 +
 11 files changed, 462 insertions(+), 3 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/AssemblyInfo.cs
 create mode 100644 test/OperationsExampleTests/.gitignore
 create mode 100644 test/OperationsExampleTests/Add/AddTests.cs
 create mode 100644 test/OperationsExampleTests/Factories/ArticleFactory.cs
 create mode 100644 test/OperationsExampleTests/OperationsExampleTests.csproj
 create mode 100644 test/OperationsExampleTests/WebHostCollection.cs
 create mode 100644 test/OperationsExampleTests/appsettings.json

diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index 74ea28c41a..86ee801e58 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -30,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReportsExample", "src\Examp
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OperationsExample", "src\Examples\OperationsExample\OperationsExample.csproj", "{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OperationsExampleTests", "test\OperationsExampleTests\OperationsExampleTests.csproj", "{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -124,6 +126,18 @@ Global
 		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.Build.0 = Release|x64
 		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.ActiveCfg = Release|x86
 		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.Build.0 = Release|x86
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.ActiveCfg = Debug|x64
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.Build.0 = Debug|x64
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.ActiveCfg = Debug|x86
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.Build.0 = Debug|x86
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.ActiveCfg = Release|x64
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.Build.0 = Release|x64
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.ActiveCfg = Release|x86
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -138,5 +152,6 @@ Global
 		{026FBC6C-AF76-4568-9B87-EC73457899FD} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
 		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
 	EndGlobalSection
 EndGlobal
diff --git a/src/JsonApiDotNetCore/AssemblyInfo.cs b/src/JsonApiDotNetCore/AssemblyInfo.cs
new file mode 100644
index 0000000000..9aa4855d37
--- /dev/null
+++ b/src/JsonApiDotNetCore/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("OperationsExampleTests")]
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
index de5ed86bf1..6f114aff33 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
@@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Formatters
 {
     public class JsonApiOperationsInputFormatter : IInputFormatter
     {
-        const string PROFILE_EXTENSION = "<http://example.org/profiles/myjsonstuff>; rel=\"profile\"";
+        internal const string PROFILE_EXTENSION = "<http://example.org/profiles/myjsonstuff>; rel=\"profile\"";
 
         public bool CanRead(InputFormatterContext context)
         {
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
index 9cfc4c177b..912cac2fff 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
@@ -22,13 +22,13 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
 
             var request = context.HttpContext.Request;
             if (request.ContentLength == null || request.ContentLength == 0)
-                return InputFormatterResult.FailureAsync();
+                throw new JsonApiException(400, "Content-Length cannot be empty.");
 
             var body = GetRequestBody(request.Body);
 
             var operations = JsonConvert.DeserializeObject<OperationsDocument>(body);
 
-            if(operations == null)
+            if (operations == null)
                 throw new JsonApiException(400, "Failed to deserialize operations request.");
 
             return InputFormatterResult.SuccessAsync(operations);
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 05394fe551..07732a2910 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -80,6 +80,8 @@ public List<TEntity> DeserializeList<TEntity>(string requestBody)
 
         public object DocumentToObject(DocumentData data)
         {
+            if (data == null) throw new JsonApiException(422, "Failed to deserialize document as json:api.");
+
             var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(data.Type?.ToString());
             _jsonApiContext.RequestEntity = contextEntity;
 
diff --git a/test/OperationsExampleTests/.gitignore b/test/OperationsExampleTests/.gitignore
new file mode 100644
index 0000000000..0ca27f04e1
--- /dev/null
+++ b/test/OperationsExampleTests/.gitignore
@@ -0,0 +1,234 @@
+## 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/test/OperationsExampleTests/Add/AddTests.cs b/test/OperationsExampleTests/Add/AddTests.cs
new file mode 100644
index 0000000000..b42dc342f1
--- /dev/null
+++ b/test/OperationsExampleTests/Add/AddTests.cs
@@ -0,0 +1,102 @@
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Extensions;
+using Microsoft.EntityFrameworkCore;
+using OperationsExample.Data;
+using OperationsExampleTests.Factories;
+using Xunit;
+
+namespace OperationsExampleTests
+{
+    [Collection("WebHostCollection")]
+    public class AddTests
+    {
+        private readonly Fixture _fixture;
+
+        public AddTests(Fixture fixture)
+        {
+            _fixture = fixture;
+        }
+
+        [Fact]
+        public async Task Can_Create_Article()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var article = ArticleFactory.Get();
+            var content = new
+            {
+                operations = new[] {
+                    new {
+                        op = "add",
+                        data = new {
+                            type = "articles",
+                            attributes = new {
+                                name = article.Name
+                            }
+                        }
+                    }
+                }
+            };
+
+            // act
+            var response = await _fixture.PatchAsync("api/bulk", content);
+
+            // assert
+            Assert.NotNull(response);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+
+            var lastArticle = await context.Articles.LastAsync();
+            Assert.Equal(article.Name, lastArticle.Name);
+        }
+
+        [Fact]
+        public async Task Can_Create_Articles()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var articles = ArticleFactory.Get(2);
+            var content = new
+            {
+                operations = new[] {
+                    new {
+                        op = "add",
+                        data = new {
+                            type = "articles",
+                            attributes = new {
+                                name = articles[0].Name
+                            }
+                        }
+                    },
+                    new {
+                        op = "add",
+                        data = new {
+                            type = "articles",
+                            attributes = new {
+                                name = articles[1].Name
+                            }
+                        }
+                    }
+                }
+            };
+
+            // act
+            var response = await _fixture.PatchAsync("api/bulk", content);
+
+            // assert
+            Assert.NotNull(response);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+
+            var lastArticles = (await context.Articles
+                .OrderByDescending(d => d.Id)
+                .Take(2)
+                .ToListAsync())
+                .OrderBy(l => l.Id)
+                .ToList();
+
+            Assert.Equal(articles[0].Name, lastArticles[0].Name);
+            Assert.Equal(articles[1].Name, lastArticles[1].Name);
+        }
+    }
+}
diff --git a/test/OperationsExampleTests/Factories/ArticleFactory.cs b/test/OperationsExampleTests/Factories/ArticleFactory.cs
new file mode 100644
index 0000000000..1907e2de24
--- /dev/null
+++ b/test/OperationsExampleTests/Factories/ArticleFactory.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using Bogus;
+using OperationsExample.Models;
+
+namespace OperationsExampleTests.Factories
+{
+    public static class ArticleFactory
+    {
+        public static Article Get()
+        {
+            var faker = new Faker<Article>();
+            faker.RuleFor(m => m.Name, f => f.Lorem.Sentence());
+            return faker.Generate();
+        }
+
+        public static List<Article> Get(int count)
+        {
+            var articles = new List<Article>();
+            for (int i = 0; i < count; i++)
+                articles.Add(Get());
+
+            return articles;
+        }
+    }
+}
\ No newline at end of file
diff --git a/test/OperationsExampleTests/OperationsExampleTests.csproj b/test/OperationsExampleTests/OperationsExampleTests.csproj
new file mode 100644
index 0000000000..18e795cb9e
--- /dev/null
+++ b/test/OperationsExampleTests/OperationsExampleTests.csproj
@@ -0,0 +1,23 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp1.1</TargetFramework>
+    <IsPackable>false</IsPackable>
+    <AssemblyName>OperationsExampleTests</AssemblyName>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.1.3" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170427-09" />
+    <PackageReference Include="moq" Version="4.7.10" />
+    <PackageReference Include="xunit" Version="2.2.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+    <PackageReference Include="Bogus" Version="8.0.1-beta-1" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Examples\OperationsExample\OperationsExample.csproj" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Update="xunit.runner.json;appsettings.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/test/OperationsExampleTests/WebHostCollection.cs b/test/OperationsExampleTests/WebHostCollection.cs
new file mode 100644
index 0000000000..a92285aff0
--- /dev/null
+++ b/test/OperationsExampleTests/WebHostCollection.cs
@@ -0,0 +1,42 @@
+using System.Net.Http;
+using Microsoft.AspNetCore.Hosting;
+using OperationsExample;
+using Xunit;
+using Microsoft.AspNetCore.TestHost;
+using Newtonsoft.Json;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Formatters;
+
+namespace OperationsExampleTests
+{
+    [CollectionDefinition("WebHostCollection")]
+    public class WebHostCollection
+        : ICollectionFixture<Fixture>
+    { }
+
+    public class Fixture
+    {
+        public Fixture()
+        {
+            var builder = new WebHostBuilder().UseStartup<Startup>();
+            Server = new TestServer(builder);
+            Client = Server.CreateClient();
+        }
+
+        public TestServer Server { get; private set; }
+        public HttpClient Client { get; }
+        public T GetService<T>() => (T)Server.Host.Services.GetService(typeof(T));
+
+        public async Task<HttpResponseMessage> PatchAsync(string route, object data)
+        {
+            var httpMethod = new HttpMethod("PATCH");
+            var request = new HttpRequestMessage(httpMethod, route);
+            request.Content = new StringContent(JsonConvert.SerializeObject(data));
+            request.Content.Headers.ContentLength = 1;
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+            request.Content.Headers.Add("Link", JsonApiOperationsInputFormatter.PROFILE_EXTENSION);
+            return await Client.SendAsync(request);
+        }
+    }
+}
\ No newline at end of file
diff --git a/test/OperationsExampleTests/appsettings.json b/test/OperationsExampleTests/appsettings.json
new file mode 100644
index 0000000000..c1061281cc
--- /dev/null
+++ b/test/OperationsExampleTests/appsettings.json
@@ -0,0 +1,13 @@
+{
+  "Data": {
+    "DefaultConnection": "Host=localhost;Port=5432;Database=OperationsExample;User ID=postgres;Password=password"
+  },
+  "Logging": {
+    "IncludeScopes": false,
+    "LogLevel": {
+      "Default": "Trace",
+      "System": "Trace",
+      "Microsoft": "Trace"
+    }
+  }
+}

From ed7659bb2a36dd6f02741617746fadc40c77c3d5 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 26 Sep 2017 23:28:22 -0500
Subject: [PATCH 025/227] feat(fetch): add get all operation

---
 .../JsonApiOperationsController.cs            |  6 +-
 .../IServiceCollectionExtensions.cs           | 10 +++
 .../Models/Operations/OperationsDocument.cs   |  8 ++
 .../Services/IJsonApiContext.cs               |  1 -
 ...r.cs => DocumentDataPointerReplacement.cs} |  0
 .../Operations/OperationProcessorResolver.cs  | 25 +++++-
 .../Operations/OperationsProcessor.cs         | 39 ++++++++-
 .../Operations/Processors/GetOpProcessor.cs   | 79 +++++++++++++++++++
 .../ResourceRefPointerReplacement.cs          | 34 ++++++++
 test/OperationsExampleTests/Get/GetTests.cs   | 49 ++++++++++++
 .../WebHostCollection.cs                      |  9 +++
 11 files changed, 251 insertions(+), 9 deletions(-)
 rename src/JsonApiDotNetCore/Services/Operations/{OperationsPointerExchanger.cs => DocumentDataPointerReplacement.cs} (100%)
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/ResourceRefPointerReplacement.cs
 create mode 100644 test/OperationsExampleTests/Get/GetTests.cs

diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
index 3990f7b85d..f3d0b6651d 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
@@ -9,7 +9,8 @@ public class JsonApiOperationsController : Controller
     {
         private readonly IOperationsProcessor _operationsProcessor;
 
-        public JsonApiOperationsController(IOperationsProcessor operationsProcessor)
+        public JsonApiOperationsController(
+            IOperationsProcessor operationsProcessor)
         {
             _operationsProcessor = operationsProcessor;
         }
@@ -18,7 +19,8 @@ public JsonApiOperationsController(IOperationsProcessor operationsProcessor)
         public async Task<IActionResult> PatchAsync([FromBody] OperationsDocument doc)
         {
             var results = await _operationsProcessor.ProcessAsync(doc.Operations);
-            return Ok(results);
+
+            return Ok(new OperationsDocument(results));
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index ab297252f9..dc9bd56cef 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -100,8 +100,13 @@ public static void AddJsonApiInternals(
             services.AddScoped<IDbContextResolver, DbContextResolver>();
             services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
             services.AddScoped(typeof(IEntityRepository<,>), typeof(DefaultEntityRepository<,>));
+            
             services.AddScoped(typeof(ICreateService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(ICreateService<,>), typeof(EntityResourceService<,>));
+
+            services.AddScoped(typeof(IGetAllService<>), typeof(EntityResourceService<>));
+            services.AddScoped(typeof(IGetAllService<,>), typeof(EntityResourceService<,>));
+
             services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IResourceService<,>), typeof(EntityResourceService<,>));
             services.AddSingleton<JsonApiOptions>(jsonApiOptions);
@@ -127,8 +132,13 @@ public static void AddJsonApiInternals(
         private static void AddOperationServices(IServiceCollection services)
         {
             services.AddScoped<IOperationsProcessor, OperationsProcessor>();
+
             services.AddScoped(typeof(ICreateOpProcessor<>), typeof(CreateOpProcessor<>));
             services.AddScoped(typeof(ICreateOpProcessor<,>), typeof(CreateOpProcessor<,>));
+
+            services.AddScoped(typeof(IGetOpProcessor<>), typeof(GetOpProcessor<>));
+            services.AddScoped(typeof(IGetOpProcessor<,>), typeof(GetOpProcessor<,>));
+
             services.AddSingleton<IOperationProcessorResolver, OperationProcessorResolver>();
             services.AddSingleton<IGenericProcessorFactory, GenericProcessorFactory>();
         }
diff --git a/src/JsonApiDotNetCore/Models/Operations/OperationsDocument.cs b/src/JsonApiDotNetCore/Models/Operations/OperationsDocument.cs
index 987f9abc20..3228e9ca88 100644
--- a/src/JsonApiDotNetCore/Models/Operations/OperationsDocument.cs
+++ b/src/JsonApiDotNetCore/Models/Operations/OperationsDocument.cs
@@ -1,9 +1,17 @@
 using System.Collections.Generic;
+using Newtonsoft.Json;
 
 namespace JsonApiDotNetCore.Models.Operations
 {
     public class OperationsDocument
     {
+        public OperationsDocument() { }
+        public OperationsDocument(List<Operation> operations) 
+        { 
+            Operations = operations;
+        }
+        
+        [JsonProperty("operations")]
         public List<Operation> Operations { get; set; }
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index 7b1b9e67a8..2a201e2691 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Reflection;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Data;
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs b/src/JsonApiDotNetCore/Services/Operations/DocumentDataPointerReplacement.cs
similarity index 100%
rename from src/JsonApiDotNetCore/Services/Operations/OperationsPointerExchanger.cs
rename to src/JsonApiDotNetCore/Services/Operations/DocumentDataPointerReplacement.cs
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
index 64261af1c7..1fbe130d0d 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -8,13 +8,15 @@ namespace JsonApiDotNetCore.Services.Operations
     public interface IOperationProcessorResolver
     {
         IOpProcessor LocateCreateService(Operation operation);
+        IOpProcessor LocateGeteService(Operation operation);
     }
 
     public class OperationProcessorResolver : IOperationProcessorResolver
     {
         private readonly IGenericProcessorFactory _processorFactory;
         private readonly IJsonApiContext _context;
-        private ConcurrentDictionary<string, IOpProcessor> _cachedProcessors = new ConcurrentDictionary<string, IOpProcessor>();
+        private ConcurrentDictionary<string, IOpProcessor> _createOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
+        private ConcurrentDictionary<string, IOpProcessor> _getOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
 
         public OperationProcessorResolver(
             IGenericProcessorFactory processorFactory,
@@ -30,7 +32,7 @@ public IOpProcessor LocateCreateService(Operation operation)
         {
             var resource = operation.GetResourceTypeName();
 
-            if (_cachedProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
+            if (_createOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
                 return cachedProcessor;
 
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
@@ -38,7 +40,24 @@ public IOpProcessor LocateCreateService(Operation operation)
                 typeof(ICreateOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
             );
 
-            _cachedProcessors[resource] = processor;
+            _createOpProcessors[resource] = processor;
+
+            return processor;
+        }
+
+        public IOpProcessor LocateGeteService(Operation operation)
+        {
+            var resource = operation.GetResourceTypeName();
+
+            if (_getOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
+                return cachedProcessor;
+
+            var contextEntity = _context.ContextGraph.GetContextEntity(resource);
+            var processor = _processorFactory.GetProcessor<IOpProcessor>(
+                typeof(IGetOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
+            );
+
+            _getOpProcessors[resource] = processor;
 
             return processor;
         }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index 75e013c8c8..bc241e72ad 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -1,5 +1,8 @@
+using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Models.Pointers;
 
@@ -28,10 +31,11 @@ public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
                 // TODO: parse pointers:
                 // locate all objects within the document and replace them
                 var operationsPointer = new OperationsPointer();
-                var replacer = new DocumentDataPointerReplacement<OperationsPointer, Operation>(op.DataObject);
-                replacer.ReplacePointers(outputOps);
 
-                var processor = _processorResolver.LocateCreateService(op);
+                ReplaceDataPointers(op.DataObject, outputOps);
+                ReplaceRefPointers(op.Ref, outputOps);
+
+                var processor = GetOperationsProcessor(op);
                 var resultOp = await processor.ProcessAsync(op);
 
                 if (resultOp != null)
@@ -40,5 +44,34 @@ public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
 
             return outputOps;
         }
+
+        private void ReplaceDataPointers(DocumentData dataObject, List<Operation> outputOps)
+        {
+            if (dataObject == null) return;
+
+            var replacer = new DocumentDataPointerReplacement<OperationsPointer, Operation>(dataObject);
+            replacer.ReplacePointers(outputOps);
+        }
+
+        private void ReplaceRefPointers(ResourceReference resourceRef, List<Operation> outputOps)
+        {
+            if (resourceRef == null) return;
+
+            var replacer = new ResourceRefPointerReplacement<OperationsPointer, Operation>(resourceRef);
+            replacer.ReplacePointers(outputOps);
+        }
+
+        private IOpProcessor GetOperationsProcessor(Operation op)
+        {
+            switch (op.Op)
+            {
+                case OperationCode.add:
+                    return _processorResolver.LocateCreateService(op);
+                case OperationCode.get:
+                    return _processorResolver.LocateGeteService(op);
+                default:
+                    throw new JsonApiException(400, $"'{op.Op}' is not a valid operation code");
+            }
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
new file mode 100644
index 0000000000..cc6f864516
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
@@ -0,0 +1,79 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Serialization;
+using JsonApiDotNetCore.Services;
+
+namespace JsonApiDotNetCore.Services.Operations.Processors
+{
+    public interface IGetOpProcessor<T> : IOpProcessor
+        where T : class, IIdentifiable<int>
+    { }
+
+    public interface IGetOpProcessor<T, TId> : IOpProcessor
+        where T : class, IIdentifiable<TId>
+    { }
+
+    public class GetOpProcessor<T> : GetOpProcessor<T, int>
+        where T : class, IIdentifiable<int>
+    {
+        public GetOpProcessor(
+            IGetAllService<T, int> service,
+            IJsonApiDeSerializer deSerializer,
+            IDocumentBuilder documentBuilder,
+            IContextGraph contextGraph,
+            IJsonApiContext jsonApiContext
+        ) : base(service, deSerializer, documentBuilder, contextGraph, jsonApiContext)
+        { }
+    }
+
+    public class GetOpProcessor<T, TId> : IGetOpProcessor<T, TId>
+         where T : class, IIdentifiable<TId>
+    {
+        private readonly IGetAllService<T, TId> _service;
+        private readonly IJsonApiDeSerializer _deSerializer;
+        private readonly IDocumentBuilder _documentBuilder;
+        private readonly IContextGraph _contextGraph;
+        private readonly IJsonApiContext _jsonApiContext;
+
+        public GetOpProcessor(
+            IGetAllService<T, TId> service,
+            IJsonApiDeSerializer deSerializer,
+            IDocumentBuilder documentBuilder,
+            IContextGraph contextGraph,
+            IJsonApiContext jsonApiContext)
+        {
+            _service = service;
+            _deSerializer = deSerializer;
+            _documentBuilder = documentBuilder;
+            _contextGraph = contextGraph;
+            _jsonApiContext = jsonApiContext.ApplyContext<T>(this);
+        }
+
+        public async Task<Operation> ProcessAsync(Operation operation)
+        {
+            var result = await _service.GetAsync();
+
+            var operationResult = new Operation
+            {
+                Op = OperationCode.add
+            };
+
+            var operations = new List<DocumentData>();
+            foreach (var resource in result)
+            {
+                var doc = _documentBuilder.GetData(
+                _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
+                resource);
+                operations.Add(doc);
+            }
+
+            operationResult.Data = operations;
+
+            return operationResult;
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Services/Operations/ResourceRefPointerReplacement.cs b/src/JsonApiDotNetCore/Services/Operations/ResourceRefPointerReplacement.cs
new file mode 100644
index 0000000000..d24d7e879a
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/ResourceRefPointerReplacement.cs
@@ -0,0 +1,34 @@
+using System.Collections.Generic;
+using JsonApiDotNetCore.Models.Pointers;
+using Newtonsoft.Json.Linq;
+using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Models.Operations;
+
+namespace JsonApiDotNetCore.Services.Operations
+{
+    public class ResourceRefPointerReplacement<TPointer, TPointerBase>
+        where TPointer : Pointer<TPointerBase>, new()
+    {
+        private readonly ResourceReference _ref;
+
+        public ResourceRefPointerReplacement(ResourceReference data)
+        {
+            _ref = data;
+        }
+
+        public void ReplacePointers(List<TPointerBase> parentDoc)
+        {
+            _ref.Id = GetPointerValue(_ref.Id, parentDoc);
+            _ref.Type = GetPointerValue(_ref.Type, parentDoc);
+        }
+
+        private object GetPointerValue(object reference, List<TPointerBase> parentDoc)
+        {
+            if (reference is JObject jObj)
+                if (jObj.TryParse<TPointer, TPointerBase>(Pointer<TPointerBase>.JsonSchema, out Pointer<TPointerBase> pointer))
+                    return pointer.GetValue(parentDoc);
+
+            return reference;
+        }
+    }
+}
\ No newline at end of file
diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs
new file mode 100644
index 0000000000..1b04df8089
--- /dev/null
+++ b/test/OperationsExampleTests/Get/GetTests.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Models.Operations;
+using Microsoft.EntityFrameworkCore;
+using OperationsExample.Data;
+using Xunit;
+
+namespace OperationsExampleTests
+{
+    [Collection("WebHostCollection")]
+    public class GetTests
+    {
+        private readonly Fixture _fixture;
+
+        public GetTests(Fixture fixture)
+        {
+            _fixture = fixture;
+        }
+
+        [Fact]
+        public async Task Can_Get_Articles()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var articles = await context.Articles.ToListAsync();
+
+            var content = new
+            {
+                operations = new[] {
+                    new Dictionary<string, object> {
+                        { "op", "get"},
+                        { "ref",  new { type = "articles" } }
+                    }
+                }
+            };
+
+            // act
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(1, result.data.Operations.Count);
+            Assert.Equal(articles.Count, result.data.Operations[0].DataList.Count);
+        }
+    }
+}
diff --git a/test/OperationsExampleTests/WebHostCollection.cs b/test/OperationsExampleTests/WebHostCollection.cs
index a92285aff0..6ddbebd433 100644
--- a/test/OperationsExampleTests/WebHostCollection.cs
+++ b/test/OperationsExampleTests/WebHostCollection.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Net.Http;
 using Microsoft.AspNetCore.Hosting;
 using OperationsExample;
@@ -38,5 +39,13 @@ public async Task<HttpResponseMessage> PatchAsync(string route, object data)
             request.Content.Headers.Add("Link", JsonApiOperationsInputFormatter.PROFILE_EXTENSION);
             return await Client.SendAsync(request);
         }
+
+        public async Task<(HttpResponseMessage response, T data)> PatchAsync<T>(string route, object data)
+        {
+            var response = await PatchAsync(route, data);
+            var json = await response.Content.ReadAsStringAsync();
+            var obj = JsonConvert.DeserializeObject<T>(json);
+            return (response, obj);
+        }
     }
 }
\ No newline at end of file

From dfd5266455de4f29c48456979c97d9d1daf95738 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 26 Sep 2017 23:42:03 -0500
Subject: [PATCH 026/227] feat(fetch): get by id operation

---
 .../IServiceCollectionExtensions.cs           |  5 +-
 .../Operations/Processors/GetOpProcessor.cs   | 47 ++++++++++++++-----
 test/OperationsExampleTests/Get/GetTests.cs   | 31 +++++++++++-
 3 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index dc9bd56cef..9985f957bc 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -100,13 +100,16 @@ public static void AddJsonApiInternals(
             services.AddScoped<IDbContextResolver, DbContextResolver>();
             services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
             services.AddScoped(typeof(IEntityRepository<,>), typeof(DefaultEntityRepository<,>));
-            
+
             services.AddScoped(typeof(ICreateService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(ICreateService<,>), typeof(EntityResourceService<,>));
 
             services.AddScoped(typeof(IGetAllService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IGetAllService<,>), typeof(EntityResourceService<,>));
 
+            services.AddScoped(typeof(IGetByIdService<>), typeof(EntityResourceService<>));
+            services.AddScoped(typeof(IGetByIdService<,>), typeof(EntityResourceService<,>));
+
             services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IResourceService<,>), typeof(EntityResourceService<,>));
             services.AddSingleton<JsonApiOptions>(jsonApiOptions);
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
index cc6f864516..8bd5b2b0f4 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
@@ -5,7 +5,6 @@
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Serialization;
-using JsonApiDotNetCore.Services;
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
@@ -21,32 +20,36 @@ public class GetOpProcessor<T> : GetOpProcessor<T, int>
         where T : class, IIdentifiable<int>
     {
         public GetOpProcessor(
-            IGetAllService<T, int> service,
+            IGetAllService<T, int> getAll,
+            IGetByIdService<T, int> getById,
             IJsonApiDeSerializer deSerializer,
             IDocumentBuilder documentBuilder,
             IContextGraph contextGraph,
             IJsonApiContext jsonApiContext
-        ) : base(service, deSerializer, documentBuilder, contextGraph, jsonApiContext)
+        ) : base(getAll, getById, deSerializer, documentBuilder, contextGraph, jsonApiContext)
         { }
     }
 
     public class GetOpProcessor<T, TId> : IGetOpProcessor<T, TId>
          where T : class, IIdentifiable<TId>
     {
-        private readonly IGetAllService<T, TId> _service;
+        private readonly IGetAllService<T, TId> _getAll;
+        private readonly IGetByIdService<T, TId> _getById;
         private readonly IJsonApiDeSerializer _deSerializer;
         private readonly IDocumentBuilder _documentBuilder;
         private readonly IContextGraph _contextGraph;
         private readonly IJsonApiContext _jsonApiContext;
 
         public GetOpProcessor(
-            IGetAllService<T, TId> service,
+            IGetAllService<T, TId> getAll,
+            IGetByIdService<T, TId> getById,
             IJsonApiDeSerializer deSerializer,
             IDocumentBuilder documentBuilder,
             IContextGraph contextGraph,
             IJsonApiContext jsonApiContext)
         {
-            _service = service;
+            _getAll = getAll;
+            _getById = getById;
             _deSerializer = deSerializer;
             _documentBuilder = documentBuilder;
             _contextGraph = contextGraph;
@@ -55,25 +58,43 @@ public GetOpProcessor(
 
         public async Task<Operation> ProcessAsync(Operation operation)
         {
-            var result = await _service.GetAsync();
-
             var operationResult = new Operation
             {
-                Op = OperationCode.add
+                Op = OperationCode.get
             };
 
+            operationResult.Data = string.IsNullOrWhiteSpace(operation.Ref.Id?.ToString())
+            ? await GetAllAsync(operation)
+            : await GetByIdAsync(operation);
+
+            return operationResult;
+        }
+
+        private async Task<object> GetAllAsync(Operation operation)
+        {
+            var result = await _getAll.GetAsync();
+
             var operations = new List<DocumentData>();
             foreach (var resource in result)
             {
                 var doc = _documentBuilder.GetData(
-                _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
-                resource);
+                    _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
+                    resource);
                 operations.Add(doc);
             }
 
-            operationResult.Data = operations;
+            return operations;
+        }
 
-            return operationResult;
+        private async Task<object> GetByIdAsync(Operation operation)
+        {
+            var id = TypeHelper.ConvertType<TId>(operation.Ref.Id);
+            var result = await _getById.GetAsync(id);
+            var doc = _documentBuilder.GetData(
+                _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
+                result);
+
+            return doc;
         }
     }
 }
diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs
index 1b04df8089..82233a4fc8 100644
--- a/test/OperationsExampleTests/Get/GetTests.cs
+++ b/test/OperationsExampleTests/Get/GetTests.cs
@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models.Operations;
@@ -43,7 +44,35 @@ public async Task Can_Get_Articles()
             Assert.NotNull(result.data);
             Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
             Assert.Equal(1, result.data.Operations.Count);
-            Assert.Equal(articles.Count, result.data.Operations[0].DataList.Count);
+            Assert.Equal(articles.Count, result.data.Operations.Single().DataList.Count);
+        }
+
+        [Fact]
+        public async Task Can_Get_Article_By_Id()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var article = await context.Articles.LastAsync();
+
+            var content = new
+            {
+                operations = new[] {
+                    new Dictionary<string, object> {
+                        { "op", "get"},
+                        { "ref",  new { type = "articles", id = article.StringId } }
+                    }
+                }
+            };
+
+            // act
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(1, result.data.Operations.Count);
+            Assert.Equal(article.Id.ToString(), result.data.Operations.Single().DataObject.Id);
         }
     }
 }

From cb1b2e4d7564ba4a669e6d192cb954d9598710ce Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 22 Oct 2017 21:14:42 -0500
Subject: [PATCH 027/227] replace operations

---
 .../IServiceCollectionExtensions.cs           |   6 +
 .../Operations/OperationProcessorResolver.cs  |  23 +++-
 .../Operations/OperationsProcessor.cs         |   4 +-
 .../Processors/ReplaceOpProcessor.cs          |  75 ++++++++++++
 test/OperationsExampleTests/Get/GetTests.cs   |  16 ++-
 .../Replace/ReplaceTests.cs                   | 112 ++++++++++++++++++
 .../WebHostCollection.cs                      |   3 +-
 7 files changed, 230 insertions(+), 9 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs
 create mode 100644 test/OperationsExampleTests/Replace/ReplaceTests.cs

diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 9985f957bc..3788f62c19 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -110,6 +110,9 @@ public static void AddJsonApiInternals(
             services.AddScoped(typeof(IGetByIdService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IGetByIdService<,>), typeof(EntityResourceService<,>));
 
+            services.AddScoped(typeof(IUpdateService<>), typeof(EntityResourceService<>));
+            services.AddScoped(typeof(IUpdateService<,>), typeof(EntityResourceService<,>));
+
             services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IResourceService<,>), typeof(EntityResourceService<,>));
             services.AddSingleton<JsonApiOptions>(jsonApiOptions);
@@ -142,6 +145,9 @@ private static void AddOperationServices(IServiceCollection services)
             services.AddScoped(typeof(IGetOpProcessor<>), typeof(GetOpProcessor<>));
             services.AddScoped(typeof(IGetOpProcessor<,>), typeof(GetOpProcessor<,>));
 
+            services.AddScoped(typeof(IReplaceOpProcessor<>), typeof(ReplaceOpProcessor<>));
+            services.AddScoped(typeof(IReplaceOpProcessor<,>), typeof(ReplaceOpProcessor<,>));
+
             services.AddSingleton<IOperationProcessorResolver, OperationProcessorResolver>();
             services.AddSingleton<IGenericProcessorFactory, GenericProcessorFactory>();
         }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
index 1fbe130d0d..544cbe9fa0 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -8,7 +8,8 @@ namespace JsonApiDotNetCore.Services.Operations
     public interface IOperationProcessorResolver
     {
         IOpProcessor LocateCreateService(Operation operation);
-        IOpProcessor LocateGeteService(Operation operation);
+        IOpProcessor LocateGetService(Operation operation);
+        IOpProcessor LocateReplaceService(Operation operation);
     }
 
     public class OperationProcessorResolver : IOperationProcessorResolver
@@ -17,6 +18,7 @@ public class OperationProcessorResolver : IOperationProcessorResolver
         private readonly IJsonApiContext _context;
         private ConcurrentDictionary<string, IOpProcessor> _createOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
         private ConcurrentDictionary<string, IOpProcessor> _getOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
+        private ConcurrentDictionary<string, IOpProcessor> _replaceOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
 
         public OperationProcessorResolver(
             IGenericProcessorFactory processorFactory,
@@ -45,7 +47,7 @@ public IOpProcessor LocateCreateService(Operation operation)
             return processor;
         }
 
-        public IOpProcessor LocateGeteService(Operation operation)
+        public IOpProcessor LocateGetService(Operation operation)
         {
             var resource = operation.GetResourceTypeName();
 
@@ -61,5 +63,22 @@ public IOpProcessor LocateGeteService(Operation operation)
 
             return processor;
         }
+
+        public IOpProcessor LocateReplaceService(Operation operation)
+        {
+            var resource = operation.GetResourceTypeName();
+
+            if (_replaceOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
+                return cachedProcessor;
+
+            var contextEntity = _context.ContextGraph.GetContextEntity(resource);
+            var processor = _processorFactory.GetProcessor<IOpProcessor>(
+                typeof(IReplaceOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
+            );
+
+            _replaceOpProcessors[resource] = processor;
+
+            return processor;
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index bc241e72ad..9a66245f67 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -68,7 +68,9 @@ private IOpProcessor GetOperationsProcessor(Operation op)
                 case OperationCode.add:
                     return _processorResolver.LocateCreateService(op);
                 case OperationCode.get:
-                    return _processorResolver.LocateGeteService(op);
+                    return _processorResolver.LocateGetService(op);
+                case OperationCode.replace:
+                    return _processorResolver.LocateReplaceService(op);
                 default:
                     throw new JsonApiException(400, $"'{op.Op}' is not a valid operation code");
             }
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs
new file mode 100644
index 0000000000..a426be7236
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Serialization;
+using Newtonsoft.Json;
+
+namespace JsonApiDotNetCore.Services.Operations.Processors
+{
+    public interface IReplaceOpProcessor<T> : IOpProcessor
+        where T : class, IIdentifiable<int>
+    { }
+
+    public interface IReplaceOpProcessor<T, TId> : IOpProcessor
+        where T : class, IIdentifiable<TId>
+    { }
+
+    public class ReplaceOpProcessor<T> : ReplaceOpProcessor<T, int>
+        where T : class, IIdentifiable<int>
+    {
+        public ReplaceOpProcessor(
+            IUpdateService<T, int> service,
+            IJsonApiDeSerializer deSerializer,
+            IDocumentBuilder documentBuilder,
+            IContextGraph contextGraph
+        ) : base(service, deSerializer, documentBuilder, contextGraph)
+        { }
+    }
+
+    public class ReplaceOpProcessor<T, TId> : IReplaceOpProcessor<T, TId>
+         where T : class, IIdentifiable<TId>
+    {
+        private readonly IUpdateService<T, TId> _service;
+        private readonly IJsonApiDeSerializer _deSerializer;
+        private readonly IDocumentBuilder _documentBuilder;
+        private readonly IContextGraph _contextGraph;
+
+        public ReplaceOpProcessor(
+            IUpdateService<T, TId> service,
+            IJsonApiDeSerializer deSerializer,
+            IDocumentBuilder documentBuilder,
+            IContextGraph contextGraph)
+        {
+            _service = service;
+            _deSerializer = deSerializer;
+            _documentBuilder = documentBuilder;
+            _contextGraph = contextGraph;
+        }
+
+        public async Task<Operation> ProcessAsync(Operation operation)
+        {
+            Console.WriteLine(JsonConvert.SerializeObject(operation));
+            var model = (T)_deSerializer.DocumentToObject(operation.DataObject);
+
+            if (string.IsNullOrWhiteSpace(operation?.DataObject?.Id?.ToString()))
+                throw new JsonApiException(400, "The data.id parameter is required for replace operations");
+
+            var id = TypeHelper.ConvertType<TId>(operation.DataObject.Id);
+            var result = await _service.UpdateAsync(id, model);
+
+            var operationResult = new Operation
+            {
+                Op = OperationCode.replace
+            };
+
+            operationResult.Data = _documentBuilder.GetData(
+                _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
+                result);
+
+            return operationResult;
+        }
+    }
+}
diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs
index 82233a4fc8..17c868cebd 100644
--- a/test/OperationsExampleTests/Get/GetTests.cs
+++ b/test/OperationsExampleTests/Get/GetTests.cs
@@ -2,9 +2,10 @@
 using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
+using Bogus;
 using JsonApiDotNetCore.Models.Operations;
-using Microsoft.EntityFrameworkCore;
 using OperationsExample.Data;
+using OperationsExampleTests.Factories;
 using Xunit;
 
 namespace OperationsExampleTests
@@ -13,6 +14,7 @@ namespace OperationsExampleTests
     public class GetTests
     {
         private readonly Fixture _fixture;
+        private readonly Faker _faker = new Faker();
 
         public GetTests(Fixture fixture)
         {
@@ -23,8 +25,12 @@ public GetTests(Fixture fixture)
         public async Task Can_Get_Articles()
         {
             // arrange
+            var expectedCount = _faker.Random.Int(1, 10);
             var context = _fixture.GetService<AppDbContext>();
-            var articles = await context.Articles.ToListAsync();
+            context.Articles.RemoveRange(context.Articles);
+            var articles = ArticleFactory.Get(expectedCount);
+            context.AddRange(articles);
+            context.SaveChanges();
 
             var content = new
             {
@@ -44,7 +50,7 @@ public async Task Can_Get_Articles()
             Assert.NotNull(result.data);
             Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
             Assert.Equal(1, result.data.Operations.Count);
-            Assert.Equal(articles.Count, result.data.Operations.Single().DataList.Count);
+            Assert.Equal(expectedCount, result.data.Operations.Single().DataList.Count);
         }
 
         [Fact]
@@ -52,7 +58,9 @@ public async Task Can_Get_Article_By_Id()
         {
             // arrange
             var context = _fixture.GetService<AppDbContext>();
-            var article = await context.Articles.LastAsync();
+            var article = ArticleFactory.Get();
+            context.Articles.Add(article);
+            context.SaveChanges();
 
             var content = new
             {
diff --git a/test/OperationsExampleTests/Replace/ReplaceTests.cs b/test/OperationsExampleTests/Replace/ReplaceTests.cs
new file mode 100644
index 0000000000..521dcd979b
--- /dev/null
+++ b/test/OperationsExampleTests/Replace/ReplaceTests.cs
@@ -0,0 +1,112 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using Bogus;
+using JsonApiDotNetCore.Models.Operations;
+using OperationsExample.Data;
+using OperationsExampleTests.Factories;
+using Xunit;
+
+namespace OperationsExampleTests
+{
+    [Collection("WebHostCollection")]
+    public class ReplaceTests
+    {
+        private readonly Fixture _fixture;
+        private readonly Faker _faker = new Faker();
+
+        public ReplaceTests(Fixture fixture)
+        {
+            _fixture = fixture;
+        }
+
+        [Fact]
+        public async Task Can_Update_Article()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var article = ArticleFactory.Get();
+            var updates = ArticleFactory.Get();
+            context.Articles.Add(article);
+            context.SaveChanges();
+
+            var content = new
+            {
+                operations = new[] {
+                    new {
+                        op = "replace",
+                        data = new {
+                            type = "articles",
+                            id = article.Id,
+                            attributes = new {
+                                name = updates.Name
+                            }
+                        }
+                    },
+                }
+            };
+
+            // act
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(1, result.data.Operations.Count);
+
+            var attrs = result.data.Operations.Single().DataObject.Attributes;
+            Assert.Equal(updates.Name, attrs["name"]);
+        }
+
+        [Fact]
+        public async Task Can_Update_Articles()
+        {
+            // arrange
+            var count = _faker.Random.Int(1, 10);
+            var context = _fixture.GetService<AppDbContext>();
+
+            var articles = ArticleFactory.Get(count);
+            var updates = ArticleFactory.Get(count);
+
+            context.Articles.AddRange(articles);
+            context.SaveChanges();
+
+            var content = new
+            {
+                operations = new List<object>()
+            };
+
+            for (int i = 0; i < count; i++)
+                content.operations.Add(new
+                {
+                    op = "replace",
+                    data = new
+                    {
+                        type = "articles",
+                        id = articles[i].Id,
+                        attributes = new
+                        {
+                            name = updates[i].Name
+                        }
+                    }
+                });
+
+            // act
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(count, result.data.Operations.Count);
+
+            for (int i = 0; i < count; i++)
+            {
+                var attrs = result.data.Operations[i].DataObject.Attributes;
+                Assert.Equal(updates[i].Name, attrs["name"]);
+            }
+        }
+    }
+}
diff --git a/test/OperationsExampleTests/WebHostCollection.cs b/test/OperationsExampleTests/WebHostCollection.cs
index 6ddbebd433..dc4f02a58c 100644
--- a/test/OperationsExampleTests/WebHostCollection.cs
+++ b/test/OperationsExampleTests/WebHostCollection.cs
@@ -12,8 +12,7 @@
 namespace OperationsExampleTests
 {
     [CollectionDefinition("WebHostCollection")]
-    public class WebHostCollection
-        : ICollectionFixture<Fixture>
+    public class WebHostCollection : ICollectionFixture<Fixture>
     { }
 
     public class Fixture

From f9761477af37f9dda783c91c04ba59b7c861cf2a Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 22 Oct 2017 21:41:08 -0500
Subject: [PATCH 028/227] remove operations

---
 .../IServiceCollectionExtensions.cs           |  6 ++
 .../Operations/OperationProcessorResolver.cs  | 22 +++++
 .../Operations/OperationsProcessor.cs         |  2 +
 .../Processors/RemoveOpProcessor.cs           | 65 +++++++++++++
 .../Processors/ReplaceOpProcessor.cs          |  3 -
 .../Remove/RemoveTests.cs                     | 92 +++++++++++++++++++
 6 files changed, 187 insertions(+), 3 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
 create mode 100644 test/OperationsExampleTests/Remove/RemoveTests.cs

diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 3788f62c19..173544c2ce 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -113,6 +113,9 @@ public static void AddJsonApiInternals(
             services.AddScoped(typeof(IUpdateService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IUpdateService<,>), typeof(EntityResourceService<,>));
 
+            services.AddScoped(typeof(IDeleteService<>), typeof(EntityResourceService<>));
+            services.AddScoped(typeof(IDeleteService<,>), typeof(EntityResourceService<,>));
+
             services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IResourceService<,>), typeof(EntityResourceService<,>));
             services.AddSingleton<JsonApiOptions>(jsonApiOptions);
@@ -148,6 +151,9 @@ private static void AddOperationServices(IServiceCollection services)
             services.AddScoped(typeof(IReplaceOpProcessor<>), typeof(ReplaceOpProcessor<>));
             services.AddScoped(typeof(IReplaceOpProcessor<,>), typeof(ReplaceOpProcessor<,>));
 
+            services.AddScoped(typeof(IRemoveOpProcessor<>), typeof(RemoveOpProcessor<>));
+            services.AddScoped(typeof(IRemoveOpProcessor<,>), typeof(RemoveOpProcessor<,>));
+
             services.AddSingleton<IOperationProcessorResolver, OperationProcessorResolver>();
             services.AddSingleton<IGenericProcessorFactory, GenericProcessorFactory>();
         }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
index 544cbe9fa0..eeadc38e22 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -10,15 +10,20 @@ public interface IOperationProcessorResolver
         IOpProcessor LocateCreateService(Operation operation);
         IOpProcessor LocateGetService(Operation operation);
         IOpProcessor LocateReplaceService(Operation operation);
+        IOpProcessor LocateRemoveService(Operation operation);
     }
 
     public class OperationProcessorResolver : IOperationProcessorResolver
     {
         private readonly IGenericProcessorFactory _processorFactory;
         private readonly IJsonApiContext _context;
+
+        // processor caches -- since there is some associated cost with creating the processors, we store them in memory
+        // to reduce the cost of subsequent requests. in the future, this may be moved into setup code run at startup
         private ConcurrentDictionary<string, IOpProcessor> _createOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
         private ConcurrentDictionary<string, IOpProcessor> _getOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
         private ConcurrentDictionary<string, IOpProcessor> _replaceOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
+        private ConcurrentDictionary<string, IOpProcessor> _removeOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
 
         public OperationProcessorResolver(
             IGenericProcessorFactory processorFactory,
@@ -80,5 +85,22 @@ public IOpProcessor LocateReplaceService(Operation operation)
 
             return processor;
         }
+
+        public IOpProcessor LocateRemoveService(Operation operation)
+        {
+            var resource = operation.GetResourceTypeName();
+
+            if (_removeOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
+                return cachedProcessor;
+
+            var contextEntity = _context.ContextGraph.GetContextEntity(resource);
+            var processor = _processorFactory.GetProcessor<IOpProcessor>(
+                typeof(IRemoveOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
+            );
+
+            _removeOpProcessors[resource] = processor;
+
+            return processor;
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index 9a66245f67..05c87dd0f7 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -71,6 +71,8 @@ private IOpProcessor GetOperationsProcessor(Operation op)
                     return _processorResolver.LocateGetService(op);
                 case OperationCode.replace:
                     return _processorResolver.LocateReplaceService(op);
+                case OperationCode.remove:
+                    return _processorResolver.LocateRemoveService(op);
                 default:
                     throw new JsonApiException(400, $"'{op.Op}' is not a valid operation code");
             }
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
new file mode 100644
index 0000000000..c96af5bb37
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Serialization;
+
+namespace JsonApiDotNetCore.Services.Operations.Processors
+{
+    public interface IRemoveOpProcessor<T> : IOpProcessor
+        where T : class, IIdentifiable<int>
+    { }
+
+    public interface IRemoveOpProcessor<T, TId> : IOpProcessor
+        where T : class, IIdentifiable<TId>
+    { }
+
+    public class RemoveOpProcessor<T> : RemoveOpProcessor<T, int>
+        where T : class, IIdentifiable<int>
+    {
+        public RemoveOpProcessor(
+            IDeleteService<T, int> service,
+            IJsonApiDeSerializer deSerializer,
+            IDocumentBuilder documentBuilder,
+            IContextGraph contextGraph
+        ) : base(service, deSerializer, documentBuilder, contextGraph)
+        { }
+    }
+
+    public class RemoveOpProcessor<T, TId> : IRemoveOpProcessor<T, TId>
+         where T : class, IIdentifiable<TId>
+    {
+        private readonly IDeleteService<T, TId> _service;
+        private readonly IJsonApiDeSerializer _deSerializer;
+        private readonly IDocumentBuilder _documentBuilder;
+        private readonly IContextGraph _contextGraph;
+
+        public RemoveOpProcessor(
+            IDeleteService<T, TId> service,
+            IJsonApiDeSerializer deSerializer,
+            IDocumentBuilder documentBuilder,
+            IContextGraph contextGraph)
+        {
+            _service = service;
+            _deSerializer = deSerializer;
+            _documentBuilder = documentBuilder;
+            _contextGraph = contextGraph;
+        }
+
+        public async Task<Operation> ProcessAsync(Operation operation)
+        {
+            var stringId = operation.Ref?.Id?.ToString();
+            if (string.IsNullOrWhiteSpace(stringId))
+                throw new JsonApiException(400, "The data.id parameter is required for delete operations");
+
+            var id = TypeHelper.ConvertType<TId>(stringId);
+            var result = await _service.DeleteAsync(id);
+
+            var operationResult = new Operation { };
+
+            return operationResult;
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs
index a426be7236..27cf348397 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs
@@ -1,11 +1,9 @@
-using System;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Serialization;
-using Newtonsoft.Json;
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
@@ -51,7 +49,6 @@ public ReplaceOpProcessor(
 
         public async Task<Operation> ProcessAsync(Operation operation)
         {
-            Console.WriteLine(JsonConvert.SerializeObject(operation));
             var model = (T)_deSerializer.DocumentToObject(operation.DataObject);
 
             if (string.IsNullOrWhiteSpace(operation?.DataObject?.Id?.ToString()))
diff --git a/test/OperationsExampleTests/Remove/RemoveTests.cs b/test/OperationsExampleTests/Remove/RemoveTests.cs
new file mode 100644
index 0000000000..f5229ebbd5
--- /dev/null
+++ b/test/OperationsExampleTests/Remove/RemoveTests.cs
@@ -0,0 +1,92 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using Bogus;
+using JsonApiDotNetCore.Models.Operations;
+using OperationsExample.Data;
+using OperationsExampleTests.Factories;
+using Xunit;
+
+namespace OperationsExampleTests
+{
+    [Collection("WebHostCollection")]
+    public class RemoveTests
+    {
+        private readonly Fixture _fixture;
+        private readonly Faker _faker = new Faker();
+
+        public RemoveTests(Fixture fixture)
+        {
+            _fixture = fixture;
+        }
+
+        [Fact]
+        public async Task Can_Remove_Article()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var article = ArticleFactory.Get();
+            context.Articles.Add(article);
+            context.SaveChanges();
+
+            var content = new
+            {
+                operations = new[] {
+                    new Dictionary<string, object> {
+                        { "op", "remove"},
+                        { "ref",  new { type = "articles", id = article.StringId } }
+                    }
+                }
+            };
+
+            // act
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(1, result.data.Operations.Count);
+            Assert.Null(context.Articles.SingleOrDefault(a => a.Id == article.Id));
+        }
+
+        [Fact]
+        public async Task Can_Remove_Articles()
+        {
+            // arrange
+            var count = _faker.Random.Int(1, 10);
+            var context = _fixture.GetService<AppDbContext>();
+
+            var articles = ArticleFactory.Get(count);
+
+            context.Articles.AddRange(articles);
+            context.SaveChanges();
+
+            var content = new
+            {
+                operations = new List<object>()
+            };
+
+            for (int i = 0; i < count; i++)
+                content.operations.Add(
+                    new Dictionary<string, object> {
+                        { "op", "remove"},
+                        { "ref",  new { type = "articles", id = articles[i].StringId } }
+                    }
+                );
+
+            // act
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(count, result.data.Operations.Count);
+
+            for (int i = 0; i < count; i++)
+                Assert.Null(context.Articles.SingleOrDefault(a => a.Id == articles[i].Id));
+        }
+    }
+}

From 05056a9e9cc952695ff93dd43757efbb3848c806 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 22 Oct 2017 22:11:00 -0500
Subject: [PATCH 029/227] wrap operations in EF transaction

---
 .../Internal/JsonApiException.cs              | 12 +--
 .../Operations/OperationsProcessor.cs         | 54 +++++++++----
 test/OperationsExampleTests/Add/AddTests.cs   | 77 ++++++++++---------
 3 files changed, 86 insertions(+), 57 deletions(-)

diff --git a/src/JsonApiDotNetCore/Internal/JsonApiException.cs b/src/JsonApiDotNetCore/Internal/JsonApiException.cs
index 9ce12fe428..aa5faf3f73 100644
--- a/src/JsonApiDotNetCore/Internal/JsonApiException.cs
+++ b/src/JsonApiDotNetCore/Internal/JsonApiException.cs
@@ -8,7 +8,7 @@ public class JsonApiException : Exception
         private readonly ErrorCollection _errors = new ErrorCollection();
 
         public JsonApiException(ErrorCollection errorCollection)
-        { 
+        {
             _errors = errorCollection;
         }
 
@@ -42,15 +42,15 @@ public JsonApiException(int statusCode, string message, Exception innerException
 
         public int GetStatusCode()
         {
-            if(_errors.Errors.Count == 1)
+            if (_errors.Errors.Count == 1)
                 return _errors.Errors[0].StatusCode;
 
-            if(_errors.Errors.FirstOrDefault(e => e.StatusCode >= 500) != null)
+            if (_errors.Errors.FirstOrDefault(e => e.StatusCode >= 500) != null)
                 return 500;
-                
-            if(_errors.Errors.FirstOrDefault(e => e.StatusCode >= 400) != null)
+
+            if (_errors.Errors.FirstOrDefault(e => e.StatusCode >= 400) != null)
                 return 400;
-            
+
             return 500;
         }
     }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index 05c87dd0f7..2873d243b1 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -5,6 +5,7 @@
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Models.Pointers;
+using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Services.Operations
 {
@@ -16,35 +17,60 @@ public interface IOperationsProcessor
     public class OperationsProcessor : IOperationsProcessor
     {
         private readonly IOperationProcessorResolver _processorResolver;
+        private readonly DbContext _dbContext;
 
-        public OperationsProcessor(IOperationProcessorResolver processorResolver)
+        public OperationsProcessor(
+            IOperationProcessorResolver processorResolver,
+            DbContext dbContext)
         {
             _processorResolver = processorResolver;
+            _dbContext = dbContext;
         }
 
         public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
         {
             var outputOps = new List<Operation>();
-
-            foreach (var op in inputOps)
+            var opIndex = 0;
+            using (var transaction = await _dbContext.Database.BeginTransactionAsync())
             {
-                // TODO: parse pointers:
-                // locate all objects within the document and replace them
-                var operationsPointer = new OperationsPointer();
-
-                ReplaceDataPointers(op.DataObject, outputOps);
-                ReplaceRefPointers(op.Ref, outputOps);
-
-                var processor = GetOperationsProcessor(op);
-                var resultOp = await processor.ProcessAsync(op);
+                try
+                {
+                    foreach (var op in inputOps)
+                    {
+                        await ProcessOperation(op, outputOps);
+                        opIndex++;
+                    }
 
-                if (resultOp != null)
-                    outputOps.Add(resultOp);
+                    transaction.Commit();
+                }
+                catch (JsonApiException e)
+                {
+                    outputOps = new List<Operation>();
+                    throw new JsonApiException(e.GetStatusCode(), $"Transaction failed on operation[{opIndex}].", e);
+                }
+                catch (Exception e)
+                {
+                    throw new JsonApiException(500, $"Transaction failed on operation[{opIndex}] for an unexpected reason.", e);
+                }
             }
 
             return outputOps;
         }
 
+        private async Task ProcessOperation(Operation op, List<Operation> outputOps)
+        {
+            var operationsPointer = new OperationsPointer();
+
+            ReplaceDataPointers(op.DataObject, outputOps);
+            ReplaceRefPointers(op.Ref, outputOps);
+
+            var processor = GetOperationsProcessor(op);
+            var resultOp = await processor.ProcessAsync(op);
+
+            if (resultOp != null)
+                outputOps.Add(resultOp);
+        }
+
         private void ReplaceDataPointers(DocumentData dataObject, List<Operation> outputOps)
         {
             if (dataObject == null) return;
diff --git a/test/OperationsExampleTests/Add/AddTests.cs b/test/OperationsExampleTests/Add/AddTests.cs
index b42dc342f1..2d765e1633 100644
--- a/test/OperationsExampleTests/Add/AddTests.cs
+++ b/test/OperationsExampleTests/Add/AddTests.cs
@@ -1,7 +1,10 @@
+using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
+using Bogus;
 using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Models.Operations;
 using Microsoft.EntityFrameworkCore;
 using OperationsExample.Data;
 using OperationsExampleTests.Factories;
@@ -13,6 +16,7 @@ namespace OperationsExampleTests
     public class AddTests
     {
         private readonly Fixture _fixture;
+        private readonly Faker _faker = new Faker();
 
         public AddTests(Fixture fixture)
         {
@@ -41,13 +45,14 @@ public async Task Can_Create_Article()
             };
 
             // act
-            var response = await _fixture.PatchAsync("api/bulk", content);
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(response);
-            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.NotNull(result);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
 
-            var lastArticle = await context.Articles.LastAsync();
+            var id = (string)result.data.Operations.Single().DataObject.Id;
+            var lastArticle = await context.Articles.SingleAsync(a => a.StringId == id);
             Assert.Equal(article.Name, lastArticle.Name);
         }
 
@@ -55,48 +60,46 @@ public async Task Can_Create_Article()
         public async Task Can_Create_Articles()
         {
             // arrange
+            var expectedCount = _faker.Random.Int(1, 10);
             var context = _fixture.GetService<AppDbContext>();
-            var articles = ArticleFactory.Get(2);
+            var articles = ArticleFactory.Get(expectedCount);
             var content = new
             {
-                operations = new[] {
-                    new {
-                        op = "add",
-                        data = new {
-                            type = "articles",
-                            attributes = new {
-                                name = articles[0].Name
-                            }
-                        }
-                    },
-                    new {
-                        op = "add",
-                        data = new {
-                            type = "articles",
-                            attributes = new {
-                                name = articles[1].Name
-                            }
-                        }
-                    }
-                }
+                operations = new List<object>()
             };
 
+            for (int i = 0; i < expectedCount; i++)
+            {
+                content.operations.Add(
+                     new
+                     {
+                         op = "add",
+                         data = new
+                         {
+                             type = "articles",
+                             attributes = new
+                             {
+                                 name = articles[i].Name
+                             }
+                         }
+                     }
+                );
+            }
+
             // act
-            var response = await _fixture.PatchAsync("api/bulk", content);
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(response);
-            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.NotNull(result);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(expectedCount, result.data.Operations.Count);
 
-            var lastArticles = (await context.Articles
-                .OrderByDescending(d => d.Id)
-                .Take(2)
-                .ToListAsync())
-                .OrderBy(l => l.Id)
-                .ToList();
-
-            Assert.Equal(articles[0].Name, lastArticles[0].Name);
-            Assert.Equal(articles[1].Name, lastArticles[1].Name);
+            for (int i = 0; i < expectedCount; i++)
+            {
+                var data = result.data.Operations[i].DataObject;
+                var article = context.Articles.Single(a => a.StringId == data.Id.ToString());
+                Assert.Equal(articles[i].Name, article.Name);
+            }
         }
     }
 }

From 8ada5c03e4259eb7abba64ab104c1b50be4a6204 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 24 Oct 2017 06:18:41 -0500
Subject: [PATCH 030/227] chore(*): bump project version and document usage

---
 couscous.yml       |  8 +++++++-
 docs/Operations.md | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 docs/Operations.md

diff --git a/couscous.yml b/couscous.yml
index 87b795a1c3..2a038cf45b 100644
--- a/couscous.yml
+++ b/couscous.yml
@@ -110,4 +110,10 @@ menu:
                     relativeUrl: entityrepositories.html
                 middleware:
                     text: Middleware
-                    relativeUrl: middleware.html
\ No newline at end of file
+                    relativeUrl: middleware.html
+        extensions:
+            name: Spec Extensions
+            items:
+                operations:
+                    text: Operations
+                    relativeUrl: operations.html
\ No newline at end of file
diff --git a/docs/Operations.md b/docs/Operations.md
new file mode 100644
index 0000000000..697f9171b2
--- /dev/null
+++ b/docs/Operations.md
@@ -0,0 +1,33 @@
+---
+currentMenu: operations
+---
+
+# Operations
+
+Operations is currently an unofficial proposal. It allows you to perform bulk operations in a single transaction. 
+
+### Enabling
+
+To enable the operations extension, modify you `Startup.ConfigureServices` method:
+
+```csharp
+services.AddJsonApi<AppDbContext>(opt => opt.EnableExtension(JsonApiExtension.Operations));
+```
+
+### Controllers
+
+To create a bulk operations controller, inherit `JsonApiOperationsController`:
+
+```csharp
+[Route("api/bulk")]
+public class OperationsController : JsonApiOperationsController
+{
+    public OperationsController(IOperationsProcessor processor)
+        : base(processor)
+    { }
+}
+```
+
+### Example
+
+There is a working example in the `/src/examples/OperationsExample` directory of the repository.
\ No newline at end of file

From 5832ea3674830bf1986092ec8a959c96ee86afd5 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 24 Oct 2017 06:46:55 -0500
Subject: [PATCH 031/227] fix tests

---
 .../Operations/OperationsProcessorTests.cs    | 23 +++++++++++++++----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
index fadcd3be78..74298f0cca 100644
--- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -1,7 +1,11 @@
 using System.Collections.Generic;
+using System.Threading;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Services.Operations;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage;
 using Moq;
 using Newtonsoft.Json;
 using Xunit;
@@ -12,9 +16,12 @@ public class OperationsProcessorTests
     {
         private readonly Mock<IOperationProcessorResolver> _resolverMock;
 
+        public readonly Mock<DbContext> _dbContextMock;
+
         public OperationsProcessorTests()
         {
             _resolverMock = new Mock<IOperationProcessorResolver>();
+            _dbContextMock = new Mock<DbContext>();
         }
 
         [Fact]
@@ -61,21 +68,27 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
                     }
                 }
             }";
-                
+
             var operations = JsonConvert.DeserializeObject<List<Operation>>(request);
             var addOperationResult = JsonConvert.DeserializeObject<Operation>(op1Result);
 
+            var databaseMock = new Mock<DatabaseFacade>(_dbContextMock.Object);
+            var transactionMock = new Mock<IDbContextTransaction>();
+            databaseMock.Setup(m => m.BeginTransactionAsync(It.IsAny<CancellationToken>()))
+                .ReturnsAsync(transactionMock.Object);
+            _dbContextMock.Setup(m => m.Database).Returns(databaseMock.Object);
+
             var opProcessorMock = new Mock<IOpProcessor>();
             opProcessorMock.Setup(m => m.ProcessAsync(It.Is<Operation>(op => op.DataObject.Type.ToString() == "authors")))
                 .ReturnsAsync(addOperationResult);
-            
+
             _resolverMock.Setup(m => m.LocateCreateService(It.IsAny<Operation>()))
                 .Returns(opProcessorMock.Object);
-            
+
             _resolverMock.Setup(m => m.LocateCreateService((It.IsAny<Operation>())))
                 .Returns(opProcessorMock.Object);
 
-            var operationsProcessor = new OperationsProcessor(_resolverMock.Object);
+            var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextMock.Object);
 
             // act
             var results = await operationsProcessor.ProcessAsync(operations);
@@ -83,7 +96,7 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
             // assert
             opProcessorMock.Verify(
                 m => m.ProcessAsync(
-                    It.Is<Operation>(o => 
+                    It.Is<Operation>(o =>
                         o.DataObject.Type.ToString() == "articles"
                         && o.DataObject.Relationships["author"].SingleData["id"].ToString() == "9"
                     )

From e4c3968eb1e6c8635c95a4e52f57792283808951 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 12 Nov 2017 20:31:58 -0600
Subject: [PATCH 032/227] chore(csproj): bump package version

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index a67648a417..e6429a1364 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.1.9</VersionPrefix>
+    <VersionPrefix>2.2.0</VersionPrefix>
     <TargetFrameworks>netstandard1.6</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From bb90f9ed60ccc2f06a42a36d4dfc657708559578 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Sun, 12 Nov 2017 20:50:15 -0600
Subject: [PATCH 033/227] feat(query-parser): allow inheritance and method
 overrides (#191)

---
 src/JsonApiDotNetCore/Services/QueryParser.cs | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 26c735e30c..297eb246a0 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -29,7 +29,7 @@ public QueryParser(
             _options = options;
         }
 
-        public QuerySet Parse(IQueryCollection query)
+        public virtual QuerySet Parse(IQueryCollection query)
         {
             var querySet = new QuerySet();
             var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>()?.QueryParams ?? QueryParams.None;
@@ -78,7 +78,7 @@ public QuerySet Parse(IQueryCollection query)
             return querySet;
         }
 
-        private List<FilterQuery> ParseFilterQuery(string key, string value)
+        protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
         {
             // expected input = filter[id]=1
             // expected input = filter[id]=eq:1
@@ -96,7 +96,7 @@ private List<FilterQuery> ParseFilterQuery(string key, string value)
             return queries;
         }
 
-        private (string operation, string value) ParseFilterOperation(string value)
+        protected virtual (string operation, string value) ParseFilterOperation(string value)
         {
             if (value.Length < 3)
                 return (string.Empty, value);
@@ -116,7 +116,7 @@ private List<FilterQuery> ParseFilterQuery(string key, string value)
             return (prefix, value);
         }
 
-        private PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value)
+        protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value)
         {
             // expected input = page[size]=10
             //                  page[number]=1
@@ -134,7 +134,7 @@ private PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value)
 
         // sort=id,name
         // sort=-id
-        private List<SortQuery> ParseSortParameters(string value)
+        protected virtual List<SortQuery> ParseSortParameters(string value)
         {
             var sortParameters = new List<SortQuery>();
             value.Split(',').ToList().ForEach(p =>
@@ -154,7 +154,7 @@ private List<SortQuery> ParseSortParameters(string value)
             return sortParameters;
         }
 
-        private List<string> ParseIncludedRelationships(string value)
+        protected virtual List<string> ParseIncludedRelationships(string value)
         {
             if (value.Contains("."))
                 throw new JsonApiException(400, "Deeply nested relationships are not supported");
@@ -164,7 +164,7 @@ private List<string> ParseIncludedRelationships(string value)
                 .ToList();
         }
 
-        private List<string> ParseFieldsQuery(string key, string value)
+        protected virtual List<string> ParseFieldsQuery(string key, string value)
         {
             // expected: fields[TYPE]=prop1,prop2
             var typeName = key.Split('[', ']')[1];
@@ -187,7 +187,7 @@ private List<string> ParseFieldsQuery(string key, string value)
             return includedFields;
         }
 
-        private AttrAttribute GetAttribute(string propertyName)
+        protected virtual AttrAttribute GetAttribute(string propertyName)
             => _controllerContext
                 .RequestEntity
                 .Attributes

From c81a7accb9735b99c156e93e360f706c980b04fa Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 12 Nov 2017 21:28:47 -0600
Subject: [PATCH 034/227] document options

---
 couscous.yml                                  |   5 +-
 docs/CustomQueryFormat.md                     |  13 ++
 docs/Options.md                               |  28 +++
 docs/QueryingData.md                          | 185 ------------------
 .../HttpMethodRestrictionFilter.cs            |   9 +-
 5 files changed, 48 insertions(+), 192 deletions(-)
 create mode 100644 docs/CustomQueryFormat.md
 delete mode 100644 docs/QueryingData.md

diff --git a/couscous.yml b/couscous.yml
index 87b795a1c3..2acaad12d7 100644
--- a/couscous.yml
+++ b/couscous.yml
@@ -110,4 +110,7 @@ menu:
                     relativeUrl: entityrepositories.html
                 middleware:
                     text: Middleware
-                    relativeUrl: middleware.html
\ No newline at end of file
+                    relativeUrl: middleware.html
+                customqueryformat:
+                    text: Custom Query Formats
+                    relativeUrl: customqueryformat.html
\ No newline at end of file
diff --git a/docs/CustomQueryFormat.md b/docs/CustomQueryFormat.md
new file mode 100644
index 0000000000..b23993d333
--- /dev/null
+++ b/docs/CustomQueryFormat.md
@@ -0,0 +1,13 @@
+---
+currentMenu: customqueryformat
+---
+
+# Custom Query Formats
+
+For information on the default query parameter formats, see the documentation for each query method.
+
+In order to customize the query formats, you need to implement the `IQueryParser` interface and inject it like so:
+
+```csharp
+services.AddScoped<IQueryParser, FooQueryParser>();
+```
\ No newline at end of file
diff --git a/docs/Options.md b/docs/Options.md
index 681c502557..3f94f4031e 100644
--- a/docs/Options.md
+++ b/docs/Options.md
@@ -80,4 +80,32 @@ Accept: application/vnd.api+json
         }
     }
 }
+```
+
+## Custom Query Parameters
+
+If you would like to use custom query params (parameters not reserved by the json:api specification), you can set `AllowCustomQueryParameters = true`. The default behavior is to return an `HTTP 400 Bad Request` for unknown query parameters.
+
+```csharp
+public IServiceProvider ConfigureServices(IServiceCollection services) {
+    services.AddJsonApi<AppDbContext>(
+        opt => opt.AllowCustomQueryParameters = true);
+    // ...
+}
+```
+
+## Custom Serializer Settings
+
+We use Json.Net for all serialization needs. If you want to change the default serializer settings, you can:
+
+```csharp
+public IServiceProvider ConfigureServices(IServiceCollection services) {
+    services.AddJsonApi<AppDbContext>(
+        opt => opt.SerializerSettings = new JsonSerializerSettings()
+        {
+            NullValueHandling = NullValueHandling.Ignore,
+            ContractResolver = new DasherizedResolver()
+        });
+    // ...
+}
 ```
\ No newline at end of file
diff --git a/docs/QueryingData.md b/docs/QueryingData.md
deleted file mode 100644
index d6de50111a..0000000000
--- a/docs/QueryingData.md
+++ /dev/null
@@ -1,185 +0,0 @@
-# Querying Data
-### Pagination
-
-Resources can be paginated. 
-The following query would set the page size to 10 and get page 2.
-
-```
-?page[size]=10&page[number]=2
-```
-
-If you would like pagination implemented by default, you can specify the page size
-when setting up the services:
-
-```csharp
- services.AddJsonApi<AppDbContext>(
-     opt => opt.DefaultPageSize = 10);
-```
-
-**Total Record Count**
-
-The total number of records can be added to the document meta by setting it in the options:
-
-```csharp
-services.AddJsonApi<AppDbContext>(opt =>
-{
-    opt.DefaultPageSize = 5;
-    opt.IncludeTotalRecordCount = true;
-});
-```
-
-### Filtering
-
-You can filter resources by attributes using the `filter` query parameter. 
-By default, all attributes are filterable.
-The filtering strategy we have selected, uses the following form:
-
-```
-?filter[attribute]=value
-```
-
-For operations other than equality, the query can be prefixed with an operation
-identifier):
-
-```
-?filter[attribute]=eq:value
-?filter[attribute]=lt:value
-?filter[attribute]=gt:value
-?filter[attribute]=le:value
-?filter[attribute]=ge:value
-?filter[attribute]=like:value
-```
-
-#### Custom Filters
-
-You can customize the filter implementation by overriding the method in the `DefaultEntityRepository` like so:
-
-```csharp
-public class MyEntityRepository : DefaultEntityRepository<MyEntity>
-{
-    public MyEntityRepository(
-    	AppDbContext context,
-        ILoggerFactory loggerFactory,
-        IJsonApiContext jsonApiContext)
-    : base(context, loggerFactory, jsonApiContext)
-    { }
-    
-    public override IQueryable<TEntity> Filter(IQueryable<TEntity> entities,  FilterQuery filterQuery)
-    {
-        // use the base filtering method    
-        entities = base.Filter(entities, filterQuery);
-	
-	// implement custom method
-	return ApplyMyCustomFilter(entities, filterQuery);
-    }
-}
-```
-
-### Sorting
-
-Resources can be sorted by an attribute:
-
-```
-?sort=attribute // ascending
-?sort=-attribute // descending
-```
-
-### Meta
-
-Meta objects can be assigned in two ways:
- - Resource meta
- - Request Meta
-
-Resource meta can be defined by implementing `IHasMeta` on the model class:
-
-```csharp
-public class Person : Identifiable<int>, IHasMeta
-{
-    // ...
-
-    public Dictionary<string, object> GetMeta(IJsonApiContext context)
-    {
-        return new Dictionary<string, object> {
-            { "copyright", "Copyright 2015 Example Corp." },
-            { "authors", new string[] { "Jared Nance" } }
-        };
-    }
-}
-```
-
-Request Meta can be added by injecting a service that implements `IRequestMeta`.
-In the event of a key collision, the Request Meta will take precendence. 
-
-### Client Generated Ids
-
-By default, the server will respond with a `403 Forbidden` HTTP Status Code if a `POST` request is
-received with a client generated id. However, this can be allowed by setting the `AllowClientGeneratedIds`
-flag in the options:
-
-```csharp
-services.AddJsonApi<AppDbContext>(opt =>
-{
-    opt.AllowClientGeneratedIds = true;
-    // ..
-});
-```
-
-### Custom Errors
-
-By default, errors will only contain the properties defined by the internal [Error](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Internal/Error.cs) class. However, you can create your own by inheriting from `Error` and either throwing it in a `JsonApiException` or returning the error from your controller.
-
-```csharp
-// custom error definition
-public class CustomError : Error {
-    public CustomError(string status, string title, string detail, string myProp)
-    : base(status, title, detail)
-    {
-        MyCustomProperty = myProp;
-    }
-    public string MyCustomProperty { get; set; }
-}
-
-// throwing a custom error
-public void MyMethod() {
-    var error = new CustomError("507", "title", "detail", "custom");
-    throw new JsonApiException(error);
-}
-
-// returning from controller
-[HttpPost]
-public override async Task<IActionResult> PostAsync([FromBody] MyEntity entity)
-{
-    if(_db.IsFull)
-        return new ObjectResult(new CustomError("507", "Database is full.", "Theres no more room.", "Sorry."));
-
-    // ...
-}
-```
-
-### Sparse Fieldsets
-
-We currently support top-level field selection. 
-What this means is you can restrict which fields are returned by a query using the `fields` query parameter, but this does not yet apply to included relationships.
-
-- Currently valid:
-```http
-GET /articles?fields[articles]=title,body HTTP/1.1
-Accept: application/vnd.api+json
-```
-
-- Not yet supported:
-```http
-GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1
-Accept: application/vnd.api+json
-```
-
-## Tests
-
-I am using DotNetCoreDocs to generate sample requests and documentation.
-
-1. To run the tests, start a postgres server and verify the connection properties define in `/test/JsonApiDotNetCoreExampleTests/appsettings.json`
-2. `cd ./test/JsonApiDotNetCoreExampleTests`
-3. `dotnet test`
-4. `cd ./src/JsonApiDotNetCoreExample`
-5. `dotnet run`
-6. `open http://localhost:5000/docs`
diff --git a/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs b/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs
index 9bf533502a..ca9a2ff138 100644
--- a/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs
+++ b/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs
@@ -1,8 +1,5 @@
-using System;
 using System.Linq;
-using System.Reflection;
 using System.Threading.Tasks;
-using JsonApiDotNetCore.Controllers;
 using JsonApiDotNetCore.Internal;
 using Microsoft.AspNetCore.Mvc.Filters;
 
@@ -17,15 +14,15 @@ public override async Task OnActionExecutionAsync(
             ActionExecutionDelegate next)
         {
             var method = context.HttpContext.Request.Method;
-            
-            if(CanExecuteAction(method) == false)
+
+            if (CanExecuteAction(method) == false)
                 throw new JsonApiException(405, $"This resource does not support {method} requests.");
 
             await next();
         }
 
         private bool CanExecuteAction(string requestMethod)
-        {            
+        {
             return Methods.Contains(requestMethod) == false;
         }
     }

From 7a42f74eb2ffdc12be35be435970d8d49385e66d Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 14 Nov 2017 21:04:46 -0600
Subject: [PATCH 035/227] chore(JsonApiContext): improve error handling if
 resource not defined on context graph

---
 .../Internal/ContextGraph.cs                  | 24 ++++++-------------
 .../Services/JsonApiContext.cs                |  2 ++
 2 files changed, 9 insertions(+), 17 deletions(-)

diff --git a/src/JsonApiDotNetCore/Internal/ContextGraph.cs b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
index aae5c2179b..fd29794194 100644
--- a/src/JsonApiDotNetCore/Internal/ContextGraph.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
@@ -8,21 +8,13 @@ namespace JsonApiDotNetCore.Internal
     public class ContextGraph : IContextGraph
     {
         public List<ContextEntity> Entities { get; set; }
-        public bool UsesDbContext  { get; set; }
+        public bool UsesDbContext { get; set; }
 
         public ContextEntity GetContextEntity(string entityName)
-        {
-            return Entities
-                .FirstOrDefault(e => 
-                    e.EntityName.ToLower() == entityName.ToLower());
-        }
+            => Entities.SingleOrDefault(e => string.Equals(e.EntityName, entityName, StringComparison.OrdinalIgnoreCase));
 
         public ContextEntity GetContextEntity(Type entityType)
-        {
-            return Entities
-                .FirstOrDefault(e => 
-                    e.EntityType == entityType);
-        }
+            => Entities.SingleOrDefault(e => e.EntityType == entityType);
 
         public object GetRelationship<TParent>(TParent entity, string relationshipName)
         {
@@ -30,9 +22,9 @@ public object GetRelationship<TParent>(TParent entity, string relationshipName)
 
             var navigationProperty = parentEntityType
                 .GetProperties()
-                .FirstOrDefault(p => p.Name.ToLower() == relationshipName.ToLower());
+                .SingleOrDefault(p => string.Equals(p.Name, relationshipName, StringComparison.OrdinalIgnoreCase));
 
-            if(navigationProperty == null)
+            if (navigationProperty == null)
                 throw new JsonApiException(400, $"{parentEntityType} does not contain a relationship named {relationshipName}");
 
             return navigationProperty.GetValue(entity);
@@ -42,11 +34,9 @@ public string GetRelationshipName<TParent>(string relationshipName)
         {
             var entityType = typeof(TParent);
             return Entities
-                .FirstOrDefault(e => 
-                    e.EntityType == entityType)
+                .SingleOrDefault(e => e.EntityType == entityType)
                 .Relationships
-                .FirstOrDefault(r => 
-                    r.PublicRelationshipName.ToLower() == relationshipName.ToLower())
+                .SingleOrDefault(r => string.Equals(r.PublicRelationshipName, relationshipName, StringComparison.OrdinalIgnoreCase))
                 ?.InternalRelationshipName;
         }
     }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index a93d76acdc..b223e47bf5 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -62,6 +62,8 @@ public IJsonApiContext ApplyContext<T>(object controller)
 
             _controllerContext.ControllerType = controller.GetType();
             _controllerContext.RequestEntity = ContextGraph.GetContextEntity(typeof(T));
+            if (_controllerContext.RequestEntity == null)
+                throw new JsonApiException(500, $"A resource has not been properly defined for type '{typeof(T)}'. Ensure it has been registered on the ContextGraph.");
 
             var context = _httpContextAccessor.HttpContext;
             var path = context.Request.Path.Value.Split('/');

From a28b17f51876263c876dc45e63a898d27ed62428 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 14 Nov 2017 20:51:41 -0600
Subject: [PATCH 036/227] fix(deserializer): skip foreign key if data not in
 relationship

also, improve the error message
---
 .../Serialization/JsonApiDeSerializer.cs      |  11 +-
 .../Serialization/JsonApiDeSerializerTests.cs | 107 +++++++++++++++++-
 2 files changed, 112 insertions(+), 6 deletions(-)

diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index d8cbf245bf..25021c441e 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -164,11 +164,6 @@ private object SetHasOneRelationship(object entity,
             ContextEntity contextEntity,
             Dictionary<string, RelationshipData> relationships)
         {
-            var entityProperty = entityProperties.FirstOrDefault(p => p.Name == $"{attr.InternalRelationshipName}Id");
-
-            if (entityProperty == null)
-                throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain an relationsip named {attr.InternalRelationshipName}");
-
             var relationshipName = attr.PublicRelationshipName;
 
             if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
@@ -181,6 +176,12 @@ private object SetHasOneRelationship(object entity,
                 if (data == null) return entity;
 
                 var newValue = data["id"];
+
+                var foreignKey = attr.InternalRelationshipName + "Id";
+                var entityProperty = entityProperties.FirstOrDefault(p => p.Name == foreignKey);
+                if (entityProperty == null)
+                    throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a foreign key property '{foreignKey}' for has one relationship '{attr.InternalRelationshipName}'");
+
                 var convertedValue = TypeHelper.ConvertType(newValue, entityProperty.PropertyType);
 
                 _jsonApiContext.RelationshipsToUpdate[relationshipAttr] = convertedValue;
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index 3e54c7b393..eeefa4d857 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Internal.Generics;
@@ -196,6 +197,98 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
                 Assert.False(attr.Key.IsImmutable);
         }
 
+        [Fact]
+        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<Independent>("independents");
+            contextGraphBuilder.AddResource<Dependent>("dependents");
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+
+            var property = Guid.NewGuid().ToString();
+            var content = new Document
+            {
+                Data = new DocumentData
+                {
+                    Type = "independents",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object> {
+                        {  "property", property }
+                    }
+                }
+            };
+
+            var contentString = JsonConvert.SerializeObject(content);
+
+            // act
+            var result = deserializer.Deserialize<Independent>(contentString);
+
+            // assert
+            Assert.NotNull(result);
+            Assert.Equal(property, result.Property);
+        }
+
+        [Fact]
+        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Relationship_Body()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<Independent>("independents");
+            contextGraphBuilder.AddResource<Dependent>("dependents");
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+
+            var property = Guid.NewGuid().ToString();
+            var content = new Document
+            {
+                Data = new DocumentData
+                {
+                    Type = "independents",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object> {
+                        {  "property", property }
+                    },
+                    // a common case for this is deserialization in unit tests
+                    Relationships = new Dictionary<string, RelationshipData> {
+                        { "dependent", new RelationshipData { } }
+                    }
+                }
+            };
+
+            var contentString = JsonConvert.SerializeObject(content);
+
+            // act
+            var result = deserializer.Deserialize<Independent>(contentString);
+
+            // assert
+            Assert.NotNull(result);
+            Assert.Equal(property, result.Property);
+        }
+
         private class TestResource : Identifiable
         {
             [Attr("complex-member")]
@@ -215,5 +308,17 @@ private class ComplexType
         {
             public string CompoundName { get; set; }
         }
+
+        private class Independent : Identifiable
+        {
+            [Attr("property")] public string Property { get; set; }
+            [HasOne("dependent")] public Dependent Dependent { get; set; }
+        }
+
+        private class Dependent : Identifiable
+        {
+            [HasOne("independent")] public Independent Independent { get; set; }
+            public int IndependentId { get; set; }
+        }
     }
 }

From 818de068d9231265bafc4242ac34d13a846d75e2 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 14 Nov 2017 20:56:23 -0600
Subject: [PATCH 037/227] chore(csproj): bump package version

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index c3c987f32a..c2a21cb7f1 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.1.9</VersionPrefix>
+    <VersionPrefix>2.1.10</VersionPrefix>
     <TargetFrameworks>netstandard1.6</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From 4be705ac66328e12d1ccdb5c115bbccbd8b1e339 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 5 Dec 2017 06:56:15 -0600
Subject: [PATCH 038/227] test(*): fix tests broken after aspnet and ef core
 2.0 upgrades

---
 .../Acceptance/Spec/CreatingDataTests.cs      |  2 +
 .../Acceptance/Spec/DocumentTests/Included.cs | 22 +++++---
 .../Spec/FetchingRelationshipsTests.cs        |  6 ++-
 .../Acceptance/Spec/PagingTests.cs            | 29 +++--------
 .../Spec/UpdatingRelationshipsTests.cs        |  1 +
 .../Acceptance/TestFixture.cs                 | 23 ++++++++-
 .../Extensions/IQueryableExtensions.cs        |  9 ++--
 .../TestFixture.cs                            | 51 -------------------
 .../WebHostCollection.cs                      |  1 +
 .../appsettings.json                          |  2 +-
 10 files changed, 61 insertions(+), 85 deletions(-)
 delete mode 100644 test/JsonApiDotNetCoreExampleTests/TestFixture.cs

diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
index e011cb8679..2f461c4f74 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
@@ -272,6 +272,8 @@ public async Task Can_Create_And_Set_HasMany_Relationships()
             var body = await response.Content.ReadAsStringAsync();
             var deserializedBody = (TodoItemCollection)_fixture.GetService<IJsonApiDeSerializer>().Deserialize(body);
             var newId = deserializedBody.Id;
+
+            context = _fixture.GetService<AppDbContext>();
             var contextCollection = context.TodoItemCollections
                 .Include(c => c.Owner)
                 .Include(c => c.TodoItems)
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
index 6ca456d680..5d4a4aa4e2 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
@@ -1,4 +1,5 @@
-using System.Linq;
+using System;
+using System.Linq;
 using System.Net;
 using System.Net.Http;
 using System.Threading.Tasks;
@@ -45,8 +46,14 @@ public Included(TestFixture<Startup> fixture)
         public async Task GET_Included_Contains_SideloadedData_ForManyToOne()
         {
             // arrange
-            var builder = new WebHostBuilder()
-                .UseStartup<Startup>();
+            var person = _personFaker.Generate();
+            var todoItem = _todoItemFaker.Generate();
+            todoItem.Owner = person;
+            _context.TodoItems.RemoveRange(_context.TodoItems);
+            _context.TodoItems.Add(todoItem);
+            _context.SaveChanges();
+
+            var builder = new WebHostBuilder().UseStartup<Startup>();
 
             var httpMethod = new HttpMethod("GET");
             var route = $"/api/v1/todo-items?include=owner";
@@ -57,13 +64,16 @@ public async Task GET_Included_Contains_SideloadedData_ForManyToOne()
 
             // act
             var response = await client.SendAsync(request);
-            var documents = JsonConvert.DeserializeObject<Documents>(await response.Content.ReadAsStringAsync());
-            var data = documents.Data[0];
 
             // assert
+            var json = await response.Content.ReadAsStringAsync();
+            var documents = JsonConvert.DeserializeObject<Documents>(json);
+            // we only care about counting the todo-items that have owners
+            var expectedCount = documents.Data.Count(d => d.Relationships["owner"].SingleData != null);
+
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotEmpty(documents.Included);
-            Assert.Equal(documents.Data.Count, documents.Included.Count);
+            Assert.Equal(expectedCount, documents.Included.Count);
         }
 
         [Fact]
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
index 51356222ba..ea805c515f 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
@@ -66,7 +66,11 @@ public async Task Request_ForRelationshipLink_ThatDoesNotExist_Returns_404()
         {
             // arrange
             var context = _fixture.GetService<AppDbContext>();
-            var todoItem = context.TodoItems.First();
+
+            var todoItem = _todoItemFaker.Generate();
+            context.TodoItems.Add(todoItem);
+            await context.SaveChangesAsync();
+
             var todoItemId = todoItem.Id;
             context.TodoItems.Remove(todoItem);
             await context.SaveChangesAsync();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
index ea99cb7d59..02dbd019e0 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
@@ -1,33 +1,22 @@
-using System.Collections.Generic;
-using System;
 using System.Linq;
 using System.Net;
-using System.Net.Http;
 using System.Threading.Tasks;
 using Bogus;
-using DotNetCoreDocs;
-using DotNetCoreDocs.Models;
-using DotNetCoreDocs.Writers;
 using JsonApiDotNetCore.Serialization;
-using JsonApiDotNetCore.Services;
 using JsonApiDotNetCoreExample;
-using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using Xunit;
 using Person = JsonApiDotNetCoreExample.Models.Person;
 
-namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
-{
-    public class PagingTests : TestFixture<Startup>
-    {
+namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec {
+    public class PagingTests : TestFixture<Startup> {
         private readonly Faker<TodoItem> _todoItemFaker = new Faker<TodoItem>()
-                .RuleFor(t => t.Description, f => f.Lorem.Sentence())
-                .RuleFor(t => t.Ordinal, f => f.Random.Number())
-                .RuleFor(t => t.CreatedDate, f => f.Date.Past());
+            .RuleFor(t => t.Description, f => f.Lorem.Sentence())
+            .RuleFor(t => t.Ordinal, f => f.Random.Number())
+            .RuleFor(t => t.CreatedDate, f => f.Date.Past());
 
         [Fact]
-        public async Task Can_Paginate_TodoItems()
-        {
+        public async Task Can_Paginate_TodoItems() {
             // Arrange
             const int expectedEntitiesPerPage = 2;
             var totalCount = expectedEntitiesPerPage * 2;
@@ -56,8 +45,7 @@ public async Task Can_Paginate_TodoItems()
         }
 
         [Fact]
-        public async Task Can_Paginate_TodoItems_From_Start()
-        {
+        public async Task Can_Paginate_TodoItems_From_Start() {
             // Arrange
             const int expectedEntitiesPerPage = 2;
             var totalCount = expectedEntitiesPerPage * 2;
@@ -91,8 +79,7 @@ public async Task Can_Paginate_TodoItems_From_Start()
         }
 
         [Fact]
-        public async Task Can_Paginate_TodoItems_From_End()
-        {
+        public async Task Can_Paginate_TodoItems_From_End() {
             // Arrange
             const int expectedEntitiesPerPage = 2;
             var totalCount = expectedEntitiesPerPage * 2;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
index d17a10c1d7..5cc3772497 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
@@ -77,6 +77,7 @@ public async Task Can_Update_ToMany_Relationship_ThroughLink()
 
             // Act
             var response = await client.SendAsync(request);
+            _context = _fixture.GetService<AppDbContext>();
             var personsTodoItems = _context.People.Include(p => p.TodoItems).Single(p => p.Id == person.Id).TodoItems;
 
             // Assert
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs
index 0379eae91d..d7ec6868b9 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs
@@ -5,11 +5,10 @@
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.TestHost;
 using JsonApiDotNetCore.Services;
-using Newtonsoft.Json;
 
 namespace JsonApiDotNetCoreExampleTests.Acceptance
 {
-    public class TestFixture<TStartup> where TStartup : class
+    public class TestFixture<TStartup> : IDisposable where TStartup : class
     {
         private readonly TestServer _server;
         private IServiceProvider _services;
@@ -33,5 +32,25 @@ public TestFixture()
         public IJsonApiDeSerializer DeSerializer { get; private set; }
         public IJsonApiContext JsonApiContext { get; private set; }
         public T GetService<T>() => (T)_services.GetService(typeof(T));
+
+        private bool disposedValue = false;
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    Client.Dispose();
+                    _server.Dispose();
+                }
+
+                disposedValue = true;
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+        }
     }
 }
\ No newline at end of file
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
index a40dfb4a5a..c774478227 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
@@ -4,12 +4,12 @@
 using Microsoft.EntityFrameworkCore.Internal;
 using Microsoft.EntityFrameworkCore.Query;
 using Microsoft.EntityFrameworkCore.Query.Internal;
+using Microsoft.EntityFrameworkCore.Storage;
 using Remotion.Linq.Parsing.Structure;
 using Database = Microsoft.EntityFrameworkCore.Storage.Database;
 
 namespace JsonApiDotNetCoreExampleTests.Helpers.Extensions
 {
-
     public static class IQueryableExtensions
     {
         private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
@@ -22,19 +22,22 @@ public static class IQueryableExtensions
 
         private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database");
 
-        private static readonly FieldInfo QueryCompilationContextFactoryField = typeof(Database).GetTypeInfo().DeclaredFields.Single(x => x.Name == "_queryCompilationContextFactory");
+        private static readonly PropertyInfo DatabaseDependenciesField
+            = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies");
 
         public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
         {
             if (!(query is EntityQueryable<TEntity>) && !(query is InternalDbSet<TEntity>))
+            {
                 throw new ArgumentException("Invalid query");
+            }
 
             var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(query.Provider);
             var nodeTypeProvider = (INodeTypeProvider)NodeTypeProviderField.GetValue(queryCompiler);
             var parser = (IQueryParser)CreateQueryParserMethod.Invoke(queryCompiler, new object[] { nodeTypeProvider });
             var queryModel = parser.GetParsedQuery(query.Expression);
             var database = DataBaseField.GetValue(queryCompiler);
-            var queryCompilationContextFactory = (IQueryCompilationContextFactory)QueryCompilationContextFactoryField.GetValue(database);
+            var queryCompilationContextFactory = ((DatabaseDependencies)DatabaseDependenciesField.GetValue(database)).QueryCompilationContextFactory;
             var queryCompilationContext = queryCompilationContextFactory.Create(false);
             var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();
             modelVisitor.CreateQueryExecutor<TEntity>(queryModel);
diff --git a/test/JsonApiDotNetCoreExampleTests/TestFixture.cs b/test/JsonApiDotNetCoreExampleTests/TestFixture.cs
deleted file mode 100644
index 424163f956..0000000000
--- a/test/JsonApiDotNetCoreExampleTests/TestFixture.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using System.Net.Http;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.TestHost;
-
-namespace JsonApiDotNetCoreExampleTests
-{
-    public class TestFixture<TStartup> : IDisposable
-        where TStartup : class
-    {
-        private readonly TestServer _server;
-        private IServiceProvider _services;
-
-        public TestFixture()
-        {
-            var builder = new WebHostBuilder()
-                .UseStartup<TStartup>();
-
-            _server = new TestServer(builder);
-            _services = _server.Host.Services;
-            Client = _server.CreateClient();
-        }
-
-        public HttpClient Client { get; set; }
-
-        public T GetService<T>()
-        {
-            return (T)_services.GetService(typeof(T));
-        }
-
-        private bool disposedValue = false;
-        protected virtual void Dispose(bool disposing)
-        {
-            if (!disposedValue)
-            {
-                if (disposing)
-                {
-                    Client.Dispose();
-                    _server.Dispose();
-                }
-
-                disposedValue = true;
-            }
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-        }
-    }
-}
\ No newline at end of file
diff --git a/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs b/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
index 01b3ace217..43a89616df 100644
--- a/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
+++ b/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
@@ -1,4 +1,5 @@
 using JsonApiDotNetCoreExample;
+using JsonApiDotNetCoreExampleTests.Acceptance;
 using Xunit;
 
 namespace JsonApiDotNetCoreExampleTests
diff --git a/test/JsonApiDotNetCoreExampleTests/appsettings.json b/test/JsonApiDotNetCoreExampleTests/appsettings.json
index 7067b2bee0..7af3457293 100644
--- a/test/JsonApiDotNetCoreExampleTests/appsettings.json
+++ b/test/JsonApiDotNetCoreExampleTests/appsettings.json
@@ -6,7 +6,7 @@
   "Logging": {
     "IncludeScopes": false,
     "LogLevel": {
-      "Default": "Debug",
+      "Default": "Error",
       "System": "Information",
       "Microsoft": "Information"
     }

From 1280195139713f5670ac0d60719d7fbf0429cd0a Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 5 Dec 2017 07:10:22 -0600
Subject: [PATCH 039/227] ci(travis): target 2.0.0 sdk

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 234e836e7e..b8a1d74643 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ services:
 before_script:
   - psql -c 'create database JsonApiDotNetCoreExample;' -U postgres
 mono: none
-dotnet: 1.0.4 # https://www.microsoft.com/net/download/linux
+dotnet: 2.0.3 # https://www.microsoft.com/net/download/linux
 branches:
   only:
     - master

From 1e932d3954aeb6f6957e0d91065e0fabf98c3577 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 5 Dec 2017 07:25:04 -0600
Subject: [PATCH 040/227] ci: remove file watching on startup classes

System.IO.IOException : The configured user limit (128) on the number of inotify instances has been reached.
---
 src/Examples/JsonApiDotNetCoreExample/Startup.cs | 2 +-
 src/Examples/NoEntityFrameworkExample/Startup.cs | 2 +-
 src/Examples/ReportsExample/Startup.cs           | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/Startup.cs b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
index 9683eb033d..1388004a55 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Startup.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
@@ -18,7 +18,7 @@ public Startup(IHostingEnvironment env)
         {
             var builder = new ConfigurationBuilder()
                 .SetBasePath(env.ContentRootPath)
-                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
+                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
                 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                 .AddEnvironmentVariables();
 
diff --git a/src/Examples/NoEntityFrameworkExample/Startup.cs b/src/Examples/NoEntityFrameworkExample/Startup.cs
index fdea4fc582..81f743aa5f 100755
--- a/src/Examples/NoEntityFrameworkExample/Startup.cs
+++ b/src/Examples/NoEntityFrameworkExample/Startup.cs
@@ -18,7 +18,7 @@ public Startup(IHostingEnvironment env)
         {
             var builder = new ConfigurationBuilder()
                 .SetBasePath(env.ContentRootPath)
-                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
                 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                 .AddEnvironmentVariables();
             Configuration = builder.Build();
diff --git a/src/Examples/ReportsExample/Startup.cs b/src/Examples/ReportsExample/Startup.cs
index 39d740da84..fed3707789 100644
--- a/src/Examples/ReportsExample/Startup.cs
+++ b/src/Examples/ReportsExample/Startup.cs
@@ -21,7 +21,7 @@ public Startup(IHostingEnvironment env)
         {
             var builder = new ConfigurationBuilder()
                 .SetBasePath(env.ContentRootPath)
-                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
+                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
                 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                 .AddEnvironmentVariables();
 

From bf357fbf2209bf9f819948defb1f550c9ba7455f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 5 Dec 2017 17:25:27 -0600
Subject: [PATCH 041/227] chore(*): fix build warnings and use new Program.cs
 format

---
 .../JsonApiDotNetCoreExample.csproj            |  4 ++--
 .../JsonApiDotNetCoreExample/Program.cs        | 18 +++++-------------
 .../NoEntityFrameworkExample/Program.cs        | 14 ++++++--------
 src/Examples/ReportsExample/Program.cs         | 14 ++++++--------
 .../CamelCasedModelsControllerTests.cs         |  1 -
 .../Acceptance/TodoItemsControllerTests.cs     | 10 +++++-----
 6 files changed, 24 insertions(+), 37 deletions(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
index e9971a1113..dcbf2a2841 100755
--- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
+++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
   <PropertyGroup>
-    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <PreserveCompilationContext>true</PreserveCompilationContext>
     <AssemblyName>JsonApiDotNetCoreExample</AssemblyName>
     <OutputType>Exe</OutputType>
@@ -13,7 +13,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(AspNetCoreVersion)" />
+    <PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="$(MicrosoftConfigurationVersion)" />
     <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="$(MicrosoftConfigurationVersion)" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftConfigurationVersion)" />
diff --git a/src/Examples/JsonApiDotNetCoreExample/Program.cs b/src/Examples/JsonApiDotNetCoreExample/Program.cs
index 16f0ad10a1..e4e3fe355e 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Program.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Program.cs
@@ -1,6 +1,5 @@
-using System.IO;
+using Microsoft.AspNetCore;
 using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
 
 namespace JsonApiDotNetCoreExample
 {
@@ -8,19 +7,12 @@ public class Program
     {
         public static void Main(string[] args)
         {
-            var config = new ConfigurationBuilder()
-                .AddCommandLine(args)
-                .AddEnvironmentVariables(prefix: "ASPNETCORE_")
-                .Build();
+            BuildWebHost(args).Run();
+        }
 
-            var host = new WebHostBuilder()
-                .UseConfiguration(config)
-                .UseKestrel()
-                .UseContentRoot(Directory.GetCurrentDirectory())
+        public static IWebHost BuildWebHost(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
                 .UseStartup<Startup>()
                 .Build();
-
-            host.Run();
-        }
     }
 }
diff --git a/src/Examples/NoEntityFrameworkExample/Program.cs b/src/Examples/NoEntityFrameworkExample/Program.cs
index 5606e8e9f4..76f3020c52 100755
--- a/src/Examples/NoEntityFrameworkExample/Program.cs
+++ b/src/Examples/NoEntityFrameworkExample/Program.cs
@@ -1,4 +1,4 @@
-using System.IO;
+using Microsoft.AspNetCore;
 using Microsoft.AspNetCore.Hosting;
 
 namespace NoEntityFrameworkExample
@@ -7,14 +7,12 @@ public class Program
     {
         public static void Main(string[] args)
         {
-            var host = new WebHostBuilder()
-                .UseKestrel()
-                .UseContentRoot(Directory.GetCurrentDirectory())
-                .UseIISIntegration()
+            BuildWebHost(args).Run();
+        }
+
+        public static IWebHost BuildWebHost(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
                 .UseStartup<Startup>()
                 .Build();
-
-            host.Run();
-        }
     }
 }
diff --git a/src/Examples/ReportsExample/Program.cs b/src/Examples/ReportsExample/Program.cs
index 41d4c37780..f3ce6c81b0 100644
--- a/src/Examples/ReportsExample/Program.cs
+++ b/src/Examples/ReportsExample/Program.cs
@@ -1,4 +1,4 @@
-using System.IO;
+using Microsoft.AspNetCore;
 using Microsoft.AspNetCore.Hosting;
 
 namespace ReportsExample
@@ -7,14 +7,12 @@ public class Program
     {
         public static void Main(string[] args)
         {
-            var host = new WebHostBuilder()
-                .UseKestrel()
-                .UseContentRoot(Directory.GetCurrentDirectory())
-                .UseIISIntegration()
+            BuildWebHost(args).Run();
+        }
+
+        public static IWebHost BuildWebHost(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
                 .UseStartup<Startup>()
                 .Build();
-
-            host.Run();
-        }
     }
 }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs
index 3cc920544f..b76293adba 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs
@@ -35,7 +35,6 @@ public CamelCasedModelsControllerTests(TestFixture<Startup> fixture)
 
         [Fact]
         public async Task Can_Get_CamelCasedModels()
-
         {
             // Arrange
             var model = _faker.Generate();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
index 3c4e748966..657e282cb8 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
@@ -219,7 +219,7 @@ public async Task Can_Get_TodoItem_ById()
             Assert.Equal(todoItem.Description, deserializedBody.Description);
             Assert.Equal(todoItem.Ordinal, deserializedBody.Ordinal);
             Assert.Equal(todoItem.CreatedDate.ToString("G"), deserializedBody.CreatedDate.ToString("G"));
-            Assert.Equal(null, deserializedBody.AchievedDate);
+            Assert.Null(deserializedBody.AchievedDate);
         }
 
         [Fact]
@@ -248,7 +248,7 @@ public async Task Can_Get_TodoItem_WithOwner()
             Assert.Equal(todoItem.Description, deserializedBody.Description);
             Assert.Equal(todoItem.Ordinal, deserializedBody.Ordinal);
             Assert.Equal(todoItem.CreatedDate.ToString("G"), deserializedBody.CreatedDate.ToString("G"));
-            Assert.Equal(null, deserializedBody.AchievedDate);
+            Assert.Null(deserializedBody.AchievedDate);
         }
 
         [Fact]
@@ -301,7 +301,7 @@ public async Task Can_Post_TodoItem()
             Assert.Equal(HttpStatusCode.Created, response.StatusCode);
             Assert.Equal(todoItem.Description, deserializedBody.Description);
             Assert.Equal(todoItem.CreatedDate.ToString("G"), deserializedBody.CreatedDate.ToString("G"));
-            Assert.Equal(null, deserializedBody.AchievedDate);
+            Assert.Null(deserializedBody.AchievedDate);
         }
 
         [Fact]
@@ -350,7 +350,7 @@ public async Task Can_Patch_TodoItem()
             Assert.Equal(newTodoItem.Description, deserializedBody.Description);
             Assert.Equal(newTodoItem.Ordinal, deserializedBody.Ordinal);
             Assert.Equal(newTodoItem.CreatedDate.ToString("G"), deserializedBody.CreatedDate.ToString("G"));
-            Assert.Equal(null, deserializedBody.AchievedDate);
+            Assert.Null(deserializedBody.AchievedDate);
         }
 
         [Fact]
@@ -453,7 +453,7 @@ public async Task Can_Patch_TodoItemWithNullValue()
             Assert.Equal(newTodoItem.Description, deserializedBody.Description);
             Assert.Equal(newTodoItem.Ordinal, deserializedBody.Ordinal);
             Assert.Equal(newTodoItem.CreatedDate.ToString("G"), deserializedBody.CreatedDate.ToString("G"));
-            Assert.Equal(null, deserializedBody.AchievedDate);
+            Assert.Null(deserializedBody.AchievedDate);
         }
 
         [Fact]

From 71a55d4613b36f5333822c0b05d0eee632a08a95 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Thu, 7 Dec 2017 05:32:31 -0600
Subject: [PATCH 042/227] docs(readme): update priorities

---
 README.md | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 46d6118fe6..360e13275d 100644
--- a/README.md
+++ b/README.md
@@ -64,9 +64,8 @@ public class Startup
 
 The current priorities for future development (in order): 
 1. Operations Support ([#150](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/150))
-2. ASP.Net Core 2.0 Support ([#161](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/161))
-3. Minor features ([#105](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/105), [#144](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/144), [#162](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/162))
-4. Resource to Entity Mapping ([#112](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/112))
+2. Minor features ([#105](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/105), [#144](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/144), [#162](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/162))
+3. Resource to Entity Mapping ([#112](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/112))
 
 If you're interested in working on any of the above features, take a look at the [Contributing Guide](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/CONTRIBUTING.MD)
 or hop on the project Gitter for more direct communication.

From 3e2cd155f3495c3ef1be8295bcb6769d2c584c23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20H=C3=BCbner?= <sven.huebner@zeiss.com>
Date: Thu, 7 Dec 2017 15:10:19 +0100
Subject: [PATCH 043/227] 200: fixed check of element type for IEnumerable<T>

---
 .../Builders/DocumentBuilder.cs               |  7 ++-
 .../Extensions/TypeExtensions.cs              | 35 +++++++++++++++
 .../Builders/DocumentBuilder_Tests.cs         | 43 +++++++++++++++++++
 3 files changed, 81 insertions(+), 4 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Extensions/TypeExtensions.cs

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index d8d38390d8..ac7e1b3ade 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -1,6 +1,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
@@ -46,9 +47,7 @@ public Document Build(IIdentifiable entity)
 
         public Documents Build(IEnumerable<IIdentifiable> entities)
         {
-            var entityType = entities
-                .GetType()
-                .GenericTypeArguments[0];
+            var entityType = entities.GetElementType();
 
             var contextEntity = _contextGraph.GetContextEntity(entityType);
 
@@ -229,7 +228,7 @@ private bool RelationshipIsIncluded(string relationshipName)
 
         private List<Dictionary<string, string>> GetRelationships(IEnumerable<object> entities)
         {
-            var objType = entities.GetType().GenericTypeArguments[0];
+            var objType = entities.GetElementType();
 
             var typeName = _jsonApiContext.ContextGraph.GetContextEntity(objType);
 
diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
new file mode 100644
index 0000000000..ccc4619966
--- /dev/null
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace JsonApiDotNetCore.Extensions
+{
+    internal static class TypeExtensions
+    {
+        public static Type GetElementType(this IEnumerable enumerable)
+        {
+            var enumerableTypes = enumerable.GetType()
+                .GetInterfaces()
+                .Where(t => t.IsGenericType == true && t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+                .ToList();
+
+            var numberOfEnumerableTypes = enumerableTypes.Count;
+
+            if (numberOfEnumerableTypes == 0)
+            {
+                throw new ArgumentException($"{nameof(enumerable)} of type {enumerable.GetType().FullName} does not implement a generic variant of {nameof(IEnumerable)}");
+            }
+
+            if (numberOfEnumerableTypes > 1)
+            {
+                throw new ArgumentException($"{nameof(enumerable)} of type {enumerable.GetType().FullName} implements more than one generic variant of {nameof(IEnumerable)}:\n" +
+                    $"{string.Join("\n", enumerableTypes.Select(t => t.FullName))}");
+            }
+
+            var elementType = enumerableTypes[0].GenericTypeArguments[0];
+
+            return elementType;
+        }
+    }
+}
diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index cd1227ef52..2cc4e7f7a3 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
@@ -118,6 +119,28 @@ public void Related_Links_Can_Be_Disabled()
             Assert.Null(document.Data.Relationships["related-model"].Links);
         }
 
+        [Fact]
+        public void Build_Can_Build_Arrays()
+        {
+            var entities = new[] { new Model() };
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+
+            var documents = documentBuilder.Build(entities);
+
+            Assert.Equal(1, documents.Data.Count);
+        }
+
+        [Fact]
+        public void Build_Can_Build_CustomIEnumerables()
+        {
+            var entities = new Models(new[] { new Model() });
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+
+            var documents = documentBuilder.Build(entities);
+
+            Assert.Equal(1, documents.Data.Count);
+        }
+
         private class Model : Identifiable
         {
             [HasOne("related-model", Link.None)]
@@ -130,5 +153,25 @@ private class RelatedModel : Identifiable
             [HasMany("models")]
             public List<Model> Models { get; set; }
         }
+
+        private class Models : IEnumerable<Model>
+        {
+            private readonly IEnumerable<Model> models;
+
+            public Models(IEnumerable<Model> models)
+            {
+                this.models = models;
+            }
+
+            public IEnumerator<Model> GetEnumerator()
+            {
+                return models.GetEnumerator();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return models.GetEnumerator();
+            }
+        }
     }
 }

From 52fc5f4bcb39478d656834b93e4babd852f5d7dd Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 11 Dec 2017 18:02:34 -0600
Subject: [PATCH 044/227] feat(JsonApiController: Expose CQRS constructor

Closes #205
---
 .../Controllers/JsonApiController.cs          | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiController.cs
index bea2105482..97350127ba 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiController.cs
@@ -16,6 +16,18 @@ public JsonApiController(
             ILoggerFactory loggerFactory)
             : base(jsonApiContext, resourceService, loggerFactory)
         { }
+
+        public JsonApiController(
+            IJsonApiContext jsonApiContext,
+            IGetAllService<T, int> getAll = null,
+            IGetByIdService<T, int> getById = null,
+            IGetRelationshipService<T, int> getRelationship = null,
+            IGetRelationshipsService<T, int> getRelationships = null,
+            ICreateService<T, int> create = null,
+            IUpdateService<T, int> update = null,
+            IUpdateRelationshipService<T, int> updateRelationships = null,
+            IDeleteService<T, int> delete = null
+        ) : base(jsonApiContext, getAll, getById, getRelationship, getRelationships, create, update, updateRelationships, delete) { }
     }
 
     public class JsonApiController<T, TId>
@@ -34,6 +46,18 @@ public JsonApiController(
         : base(jsonApiContext, resourceService)
         { }
 
+        public JsonApiController(
+           IJsonApiContext jsonApiContext,
+            IGetAllService<T, TId> getAll = null,
+            IGetByIdService<T, TId> getById = null,
+            IGetRelationshipService<T, TId> getRelationship = null,
+            IGetRelationshipsService<T, TId> getRelationships = null,
+            ICreateService<T, TId> create = null,
+            IUpdateService<T, TId> update = null,
+            IUpdateRelationshipService<T, TId> updateRelationships = null,
+            IDeleteService<T, TId> delete = null
+        ) : base(jsonApiContext, getAll, getById, getRelationship, getRelationships, create, update, updateRelationships, delete) { }
+
         [HttpGet]
         public override async Task<IActionResult> GetAsync() => await base.GetAsync();
 

From ad0ca38a120237c8b2142180c62768a57c78b3a4 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Mon, 11 Dec 2017 18:18:31 -0600
Subject: [PATCH 045/227] docs(readme): fix appveyor link

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 360e13275d..1acbbbf799 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 
 # JSON API .Net Core
 
-[![Build status](https://ci.appveyor.com/api/projects/status/9fvgeoxdikwkom10?svg=true)](https://ci.appveyor.com/project/jaredcnance/json-api-dotnet-core)
+[![Build status](https://ci.appveyor.com/api/projects/status/9fvgeoxdikwkom10?svg=true)](https://ci.appveyor.com/project/jaredcnance/jsonapidotnetcore)
 [![Travis](https://travis-ci.org/json-api-dotnet/JsonApiDotNetCore.svg?branch=master)](https://travis-ci.org/json-api-dotnet/JsonApiDotNetCore)
 [![NuGet](https://img.shields.io/nuget/v/JsonApiDotNetCore.svg)](https://www.nuget.org/packages/JsonApiDotNetCore/)
 [![MyGet CI](https://img.shields.io/myget/research-institute/vpre/JsonApiDotNetCore.svg)](https://www.myget.org/feed/research-institute/package/nuget/JsonApiDotNetCore)

From 192513edc38468a2ecc173e63d86520338d50497 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 14 Nov 2017 21:53:30 -0600
Subject: [PATCH 046/227] feat(*): add benchmarks project and
 dependencies.props

---
 .editorconfig                                 |  14 ++
 JsonApiDotnetCore.sln                         |  25 +-
 benchmarks/Benchmarks/.gitignore              | 236 ++++++++++++++++++
 ...piDeserializer_Benchmarks-report-github.md |  13 +
 ....JsonApiDeserializer_Benchmarks-report.csv |   2 +
 ...JsonApiDeserializer_Benchmarks-report.html |  30 +++
 benchmarks/Benchmarks/Benchmarks.csproj       |  15 ++
 benchmarks/Benchmarks/Program.cs              |  10 +
 .../JsonApiDeserializer_Benchmarks.cs         |  59 +++++
 build/dependencies.props                      |  11 +
 .../JsonApiDotNetCoreExample.csproj           |   2 +-
 .../NoEntityFrameworkExample.csproj           |   2 +-
 .../ReportsExample/ReportsExample.csproj      |  48 ++--
 .../JsonApiDotNetCore.csproj                  |   2 +
 .../JsonApiDotNetCoreExampleTests.csproj      |   2 +-
 .../NoEntityFrameworkTests.csproj             |   2 +-
 .../Serialization/JsonApiDeSerializerTests.cs | 161 +++++-------
 test/UnitTests/UnitTests.csproj               |   3 +-
 18 files changed, 512 insertions(+), 125 deletions(-)
 create mode 100644 .editorconfig
 create mode 100644 benchmarks/Benchmarks/.gitignore
 create mode 100755 benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
 create mode 100755 benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
 create mode 100755 benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
 create mode 100644 benchmarks/Benchmarks/Benchmarks.csproj
 create mode 100644 benchmarks/Benchmarks/Program.cs
 create mode 100644 benchmarks/Benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
 create mode 100644 build/dependencies.props

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000..134066baff
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+charset = utf-8
+
+[*.{csproj,props}]
+indent_size = 2
diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index a144223671..ef4c03dc49 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -28,6 +28,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{02
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReportsExample", "src\Examples\ReportsExample\ReportsExample.csproj", "{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}"
 EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{076E1AE4-FD25-4684-B826-CAAE37FEA0AA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "benchmarks\Benchmarks\Benchmarks.csproj", "{1F604666-BB0F-413E-922D-9D37C6073285}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -106,10 +110,22 @@ Global
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Debug|x86.Build.0 = Debug|Any CPU
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|Any CPU.Build.0 = Release|Any CPU
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.ActiveCfg = Release|Any CPU
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|Any CPU
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|Any CPU
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|Any CPU
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.ActiveCfg = Release|x64
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|x64
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|x86
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|x86
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x64.ActiveCfg = Debug|x64
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x64.Build.0 = Debug|x64
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x86.ActiveCfg = Debug|x86
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x86.Build.0 = Debug|x86
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|Any CPU.Build.0 = Release|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x64.ActiveCfg = Release|x64
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x64.Build.0 = Release|x64
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.ActiveCfg = Release|x86
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -123,6 +139,7 @@ Global
 		{6D4BD85A-A262-44C6-8572-FE3A30410BF3} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
 		{026FBC6C-AF76-4568-9B87-EC73457899FD} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
+		{1F604666-BB0F-413E-922D-9D37C6073285} = {076E1AE4-FD25-4684-B826-CAAE37FEA0AA}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4}
diff --git a/benchmarks/Benchmarks/.gitignore b/benchmarks/Benchmarks/.gitignore
new file mode 100644
index 0000000000..0f552f400b
--- /dev/null
+++ b/benchmarks/Benchmarks/.gitignore
@@ -0,0 +1,236 @@
+_data/
+
+## 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/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md b/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
new file mode 100755
index 0000000000..1eacea495f
--- /dev/null
+++ b/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
@@ -0,0 +1,13 @@
+``` 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.29 us | 0.5275 us | 0.5863 us |
diff --git a/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv b/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
new file mode 100755
index 0000000000..1a8fbe9734
--- /dev/null
+++ b/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
@@ -0,0 +1,2 @@
+Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,EnvironmentVariables,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Mean,Error,StdDev
+DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,27.29 us,0.5275 us,0.5863 us
diff --git a/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html b/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
new file mode 100755
index 0000000000..c7e5ed02a4
--- /dev/null
+++ b/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<meta charset='utf-8' />
+<title>JsonApiDeserializer_Benchmarks</title>
+
+<style type="text/css">
+	table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
+	td, th { padding: 6px 13px; border: 1px solid #ddd; }
+	tr { background-color: #fff; border-top: 1px solid #ccc; }
+	tr:nth-child(even) { background: #f8f8f8; }
+</style>
+</head>
+<body>
+<pre><code>
+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
+</code></pre>
+<pre><code></code></pre>
+
+<table>
+<thead><tr><th>           Method</th><th>Mean</th><th>Error</th><th>StdDev</th>
+</tr>
+</thead><tbody><tr><td>DeserializeSimpleObject</td><td>27.29 us</td><td>0.5275 us</td><td>0.5863 us</td>
+</tr></tbody></table>
+</body>
+</html>
diff --git a/benchmarks/Benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks/Benchmarks.csproj
new file mode 100644
index 0000000000..a7a1593823
--- /dev/null
+++ b/benchmarks/Benchmarks/Benchmarks.csproj
@@ -0,0 +1,15 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <Import Project="..\..\build\dependencies.props" />
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="BenchmarkDotNet" Version="0.10.10" />
+    <PackageReference Include="moq" Version="$(MoqVersion)" />
+    <PackageReference Include="xunit" Version="$(xUnitVersion)" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
+  </ItemGroup>
+</Project>
diff --git a/benchmarks/Benchmarks/Program.cs b/benchmarks/Benchmarks/Program.cs
new file mode 100644
index 0000000000..be5115f62c
--- /dev/null
+++ b/benchmarks/Benchmarks/Program.cs
@@ -0,0 +1,10 @@
+using BenchmarkDotNet.Running;
+using Benchmarks.Serialization;
+
+namespace Benchmarks {
+    class Program {
+        static void Main(string[] args) {
+            var summary = BenchmarkRunner.Run<JsonApiDeserializer_Benchmarks>();
+        }
+    }
+}
diff --git a/benchmarks/Benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs b/benchmarks/Benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
new file mode 100644
index 0000000000..9303b4d4c1
--- /dev/null
+++ b/benchmarks/Benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using BenchmarkDotNet.Attributes;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Internal.Generics;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Serialization;
+using JsonApiDotNetCore.Services;
+using Moq;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+
+namespace Benchmarks.Serialization {
+    public class JsonApiDeserializer_Benchmarks {
+        private const string TYPE_NAME = "simple-types";
+        private static readonly string Content = JsonConvert.SerializeObject(new Document {
+            Data = new DocumentData {
+                Type = TYPE_NAME,
+                    Id = "1",
+                    Attributes = new Dictionary<string, object> {
+                        {
+                            "name",
+                            Guid.NewGuid().ToString()
+                        }
+                    }
+            }
+        });
+
+        private readonly JsonApiDeSerializer _jsonApiDeSerializer;
+
+        public JsonApiDeserializer_Benchmarks() {
+            var contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<SimpleType>(TYPE_NAME);
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+
+            _jsonApiDeSerializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+        }
+
+        [Benchmark]
+        public object DeserializeSimpleObject() => _jsonApiDeSerializer.Deserialize<SimpleType>(Content);
+
+        private class SimpleType : Identifiable {
+            [Attr("name")]
+            public string Name { get; set; }
+        }
+    }
+}
diff --git a/build/dependencies.props b/build/dependencies.props
new file mode 100644
index 0000000000..d4686bba2e
--- /dev/null
+++ b/build/dependencies.props
@@ -0,0 +1,11 @@
+<Project>
+  <PropertyGroup>
+    <NetCoreAppVersion>netcoreapp1.1</NetCoreAppVersion>
+    <NetStandardVersion>netstandard1.6</NetStandardVersion>
+  </PropertyGroup>
+  <PropertyGroup>
+    <MoqVersion>4.7.10</MoqVersion>
+    <xUnitVersion>2.2.0</xUnitVersion>
+    <BogusVersion>8.0.1-beta-1</BogusVersion>
+  </PropertyGroup>
+</Project>
diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
index dcbf2a2841..a2981cffd1 100755
--- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
+++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
@@ -1,5 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
-
+  <Import Project="..\..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <PreserveCompilationContext>true</PreserveCompilationContext>
diff --git a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
index afaf0e7cff..32506808fe 100755
--- a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
+++ b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
@@ -1,5 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
-
+  <Import Project="..\..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
   </PropertyGroup>
diff --git a/src/Examples/ReportsExample/ReportsExample.csproj b/src/Examples/ReportsExample/ReportsExample.csproj
index 2131c545a4..f8f83e454c 100644
--- a/src/Examples/ReportsExample/ReportsExample.csproj
+++ b/src/Examples/ReportsExample/ReportsExample.csproj
@@ -1,24 +1,24 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
-
-  <PropertyGroup>
-    <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <Folder Include="wwwroot\" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="../../JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
-    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
-    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftLoggingVersion)" />
-    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
-    <PackageReference Include="Npgsql" Version="$(NpgsqlVersion)" />
-    <PackageReference Include="Dapper" Version="1.50.2" />
-  </ItemGroup>
-
-</Project>
+<Project Sdk="Microsoft.NET.Sdk.Web">
+  <Import Project="..\..\..\build\dependencies.props" />
+  <PropertyGroup>
+    <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Folder Include="wwwroot\" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="../../JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftLoggingVersion)" />
+    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
+    <PackageReference Include="Npgsql" Version="$(NpgsqlVersion)" />
+    <PackageReference Include="Dapper" Version="1.50.2" />
+  </ItemGroup>
+
+</Project>
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 9ebddb4512..53c81b2ec1 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,4 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
+  <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <VersionPrefix>2.2.0</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
@@ -20,4 +21,5 @@
     <PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftLoggingVersion)" />
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
   </ItemGroup>
+
 </Project>
diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
index b22953dc23..1b40e2dd73 100755
--- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
@@ -1,5 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
-
+  <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <PreserveCompilationContext>true</PreserveCompilationContext>
diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
index 8daa7dc9af..5553a7c1eb 100644
--- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
+++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
@@ -1,5 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
-
+  <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <PreserveCompilationContext>true</PreserveCompilationContext>
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index eeefa4d857..5096cbac31 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -11,13 +11,10 @@
 using Newtonsoft.Json.Serialization;
 using Xunit;
 
-namespace UnitTests.Serialization
-{
-    public class JsonApiDeSerializerTests
-    {
+namespace UnitTests.Serialization {
+    public class JsonApiDeSerializerTests {
         [Fact]
-        public void Can_Deserialize_Complex_Types()
-        {
+        public void Can_Deserialize_Complex_Types() {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -36,17 +33,16 @@ public void Can_Deserialize_Complex_Types()
 
             var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
 
-            var content = new Document
-            {
-                Data = new DocumentData
+            var content = new Document {
+                Data = new DocumentData {
+                Type = "test-resource",
+                Id = "1",
+                Attributes = new Dictionary<string, object> {
                 {
-                    Type = "test-resource",
-                    Id = "1",
-                    Attributes = new Dictionary<string, object> {
-                        {
-                            "complex-member", new { compoundName = "testName" }
-                        }
-                    }
+                "complex-member",
+                new { compoundName = "testName" }
+                }
+                }
                 }
             };
 
@@ -59,8 +55,7 @@ public void Can_Deserialize_Complex_Types()
         }
 
         [Fact]
-        public void Can_Deserialize_Complex_List_Types()
-        {
+        public void Can_Deserialize_Complex_List_Types() {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResourceWithList>("test-resource");
@@ -78,19 +73,18 @@ public void Can_Deserialize_Complex_List_Types()
 
             var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
 
-            var content = new Document
-            {
-                Data = new DocumentData
+            var content = new Document {
+                Data = new DocumentData {
+                Type = "test-resource",
+                Id = "1",
+                Attributes = new Dictionary<string, object> {
                 {
-                    Type = "test-resource",
-                    Id = "1",
-                    Attributes = new Dictionary<string, object> {
-                        {
-                            "complex-members", new [] {
-                                new { compoundName = "testName" }
-                            }
-                        }
-                    }
+                "complex-members",
+                new [] {
+                new { compoundName = "testName" }
+                }
+                }
+                }
                 }
             };
 
@@ -104,8 +98,7 @@ public void Can_Deserialize_Complex_List_Types()
         }
 
         [Fact]
-        public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs()
-        {
+        public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs() {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -124,17 +117,16 @@ public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs()
 
             var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
 
-            var content = new Document
-            {
-                Data = new DocumentData
+            var content = new Document {
+                Data = new DocumentData {
+                Type = "test-resource",
+                Id = "1",
+                Attributes = new Dictionary<string, object> {
                 {
-                    Type = "test-resource",
-                    Id = "1",
-                    Attributes = new Dictionary<string, object> {
-                        {
-                            "complex-member", new Dictionary<string, string> { { "compound-name",  "testName" } }
-                        }
-                    }
+                "complex-member",
+                new Dictionary<string, string> { { "compound-name", "testName" } }
+                }
+                }
                 }
             };
 
@@ -147,8 +139,7 @@ public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs()
         }
 
         [Fact]
-        public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
-        {
+        public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate() {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -169,18 +160,18 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
 
             var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
 
-            var content = new Document
-            {
-                Data = new DocumentData
+            var content = new Document {
+                Data = new DocumentData {
+                Type = "test-resource",
+                Id = "1",
+                Attributes = new Dictionary<string, object> {
                 {
-                    Type = "test-resource",
-                    Id = "1",
-                    Attributes = new Dictionary<string, object> {
-                        { "complex-member", new Dictionary<string, string> {
-                            { "compound-name",  "testName" } }
-                        },
-                        {  "immutable", "value"}
-                    }
+                "complex-member",
+                new Dictionary<string, string> { { "compound-name", "testName" }
+                }
+                },
+                { "immutable", "value" }
+                }
                 }
             };
 
@@ -198,8 +189,7 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
         }
 
         [Fact]
-        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship()
-        {
+        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship() {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<Independent>("independents");
@@ -219,15 +209,12 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship()
             var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
 
             var property = Guid.NewGuid().ToString();
-            var content = new Document
-            {
-                Data = new DocumentData
-                {
-                    Type = "independents",
-                    Id = "1",
-                    Attributes = new Dictionary<string, object> {
-                        {  "property", property }
-                    }
+            var content = new Document {
+                Data = new DocumentData {
+                Type = "independents",
+                Id = "1",
+                Attributes = new Dictionary<string, object> { { "property", property }
+                }
                 }
             };
 
@@ -242,8 +229,7 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship()
         }
 
         [Fact]
-        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Relationship_Body()
-        {
+        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Relationship_Body() {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<Independent>("independents");
@@ -263,19 +249,15 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Rel
             var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
 
             var property = Guid.NewGuid().ToString();
-            var content = new Document
-            {
-                Data = new DocumentData
-                {
-                    Type = "independents",
-                    Id = "1",
-                    Attributes = new Dictionary<string, object> {
-                        {  "property", property }
-                    },
-                    // a common case for this is deserialization in unit tests
-                    Relationships = new Dictionary<string, RelationshipData> {
-                        { "dependent", new RelationshipData { } }
-                    }
+            var content = new Document {
+                Data = new DocumentData {
+                Type = "independents",
+                Id = "1",
+                Attributes = new Dictionary<string, object> { { "property", property }
+                },
+                // a common case for this is deserialization in unit tests
+                Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } }
+                }
                 }
             };
 
@@ -289,34 +271,29 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Rel
             Assert.Equal(property, result.Property);
         }
 
-        private class TestResource : Identifiable
-        {
+        private class TestResource : Identifiable {
             [Attr("complex-member")]
             public ComplexType ComplexMember { get; set; }
 
-            [Attr("immutable", isImmutable: true)]
+            [Attr("immutable", isImmutable : true)]
             public string Immutable { get; set; }
         }
 
-        private class TestResourceWithList : Identifiable
-        {
+        private class TestResourceWithList : Identifiable {
             [Attr("complex-members")]
             public List<ComplexType> ComplexMembers { get; set; }
         }
 
-        private class ComplexType
-        {
+        private class ComplexType {
             public string CompoundName { get; set; }
         }
 
-        private class Independent : Identifiable
-        {
+        private class Independent : Identifiable {
             [Attr("property")] public string Property { get; set; }
             [HasOne("dependent")] public Dependent Dependent { get; set; }
         }
 
-        private class Dependent : Identifiable
-        {
+        private class Dependent : Identifiable {
             [HasOne("independent")] public Independent Independent { get; set; }
             public int IndependentId { get; set; }
         }
diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj
index dcd659d2df..4848455eac 100644
--- a/test/UnitTests/UnitTests.csproj
+++ b/test/UnitTests/UnitTests.csproj
@@ -1,4 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
+  <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <IsPackable>false</IsPackable>
@@ -13,4 +14,4 @@
     <PackageReference Include="xunit" Version="$(XUnitVersion)" />
     <PackageReference Include="Moq" Version="$(MoqVersion)" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>

From c9b6c11d3dad6aa3e3bc2abc6f87bd4ebd43c30f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 14 Nov 2017 21:58:07 -0600
Subject: [PATCH 047/227] chore(benchmarks): remove parent dir

---
 JsonApiDotnetCore.sln                                         | 2 +-
 benchmarks/{Benchmarks => }/.gitignore                        | 0
 ...ialization.JsonApiDeserializer_Benchmarks-report-github.md | 0
 ...ks.Serialization.JsonApiDeserializer_Benchmarks-report.csv | 0
 ...s.Serialization.JsonApiDeserializer_Benchmarks-report.html | 0
 benchmarks/{Benchmarks => }/Benchmarks.csproj                 | 4 ++--
 benchmarks/{Benchmarks => }/Program.cs                        | 0
 .../Serialization/JsonApiDeserializer_Benchmarks.cs           | 0
 8 files changed, 3 insertions(+), 3 deletions(-)
 rename benchmarks/{Benchmarks => }/.gitignore (100%)
 rename benchmarks/{Benchmarks => }/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md (100%)
 rename benchmarks/{Benchmarks => }/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv (100%)
 rename benchmarks/{Benchmarks => }/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html (100%)
 rename benchmarks/{Benchmarks => }/Benchmarks.csproj (75%)
 rename benchmarks/{Benchmarks => }/Program.cs (100%)
 rename benchmarks/{Benchmarks => }/Serialization/JsonApiDeserializer_Benchmarks.cs (100%)

diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index ef4c03dc49..385fa4d6ad 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -30,7 +30,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReportsExample", "src\Examp
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{076E1AE4-FD25-4684-B826-CAAE37FEA0AA}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "benchmarks\Benchmarks\Benchmarks.csproj", "{1F604666-BB0F-413E-922D-9D37C6073285}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "benchmarks\Benchmarks.csproj", "{1F604666-BB0F-413E-922D-9D37C6073285}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/benchmarks/Benchmarks/.gitignore b/benchmarks/.gitignore
similarity index 100%
rename from benchmarks/Benchmarks/.gitignore
rename to benchmarks/.gitignore
diff --git a/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
similarity index 100%
rename from benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
rename to benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
diff --git a/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
similarity index 100%
rename from benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
rename to benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
diff --git a/benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
similarity index 100%
rename from benchmarks/Benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
rename to benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
diff --git a/benchmarks/Benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj
similarity index 75%
rename from benchmarks/Benchmarks/Benchmarks.csproj
rename to benchmarks/Benchmarks.csproj
index a7a1593823..107fd008c2 100644
--- a/benchmarks/Benchmarks/Benchmarks.csproj
+++ b/benchmarks/Benchmarks.csproj
@@ -1,5 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
-  <Import Project="..\..\build\dependencies.props" />
+  <Import Project="..\build\dependencies.props" />
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
@@ -10,6 +10,6 @@
     <PackageReference Include="xunit" Version="$(xUnitVersion)" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\src\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
+    <ProjectReference Include="..\src\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
   </ItemGroup>
 </Project>
diff --git a/benchmarks/Benchmarks/Program.cs b/benchmarks/Program.cs
similarity index 100%
rename from benchmarks/Benchmarks/Program.cs
rename to benchmarks/Program.cs
diff --git a/benchmarks/Benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs b/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
similarity index 100%
rename from benchmarks/Benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
rename to benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs

From 53ad46f4b1e998124aefaa921076f77b816f0aec Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 14 Nov 2017 22:07:25 -0600
Subject: [PATCH 048/227] bench(serializer): test simple object serialization

---
 ...piDeserializer_Benchmarks-report-github.md |  2 +-
 ....JsonApiDeserializer_Benchmarks-report.csv |  2 +-
 ...JsonApiDeserializer_Benchmarks-report.html |  2 +-
 ...nApiSerializer_Benchmarks-report-github.md | 13 +++++
 ...on.JsonApiSerializer_Benchmarks-report.csv |  2 +
 ...n.JsonApiSerializer_Benchmarks-report.html | 30 ++++++++++++
 benchmarks/Program.cs                         |  3 +-
 .../JsonApiSerializer_Benchmarks.cs           | 49 +++++++++++++++++++
 8 files changed, 99 insertions(+), 4 deletions(-)
 create mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
 create mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
 create mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html
 create mode 100644 benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs

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
index 1eacea495f..2004bb0243 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
@@ -10,4 +10,4 @@ Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
 ```
 |                  Method |     Mean |     Error |    StdDev |
 |------------------------ |---------:|----------:|----------:|
-| DeserializeSimpleObject | 27.29 us | 0.5275 us | 0.5863 us |
+| DeserializeSimpleObject | 27.34 us | 0.5458 us | 0.7472 us |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
index 1a8fbe9734..230be6418f 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
@@ -1,2 +1,2 @@
 Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,EnvironmentVariables,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Mean,Error,StdDev
-DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,27.29 us,0.5275 us,0.5863 us
+DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,27.34 us,0.5458 us,0.7472 us
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
index c7e5ed02a4..e1906ca4e0 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
@@ -24,7 +24,7 @@
 <table>
 <thead><tr><th>           Method</th><th>Mean</th><th>Error</th><th>StdDev</th>
 </tr>
-</thead><tbody><tr><td>DeserializeSimpleObject</td><td>27.29 us</td><td>0.5275 us</td><td>0.5863 us</td>
+</thead><tbody><tr><td>DeserializeSimpleObject</td><td>27.34 us</td><td>0.5458 us</td><td>0.7472 us</td>
 </tr></tbody></table>
 </body>
 </html>
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
new file mode 100755
index 0000000000..66104fb0a2
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
@@ -0,0 +1,13 @@
+``` 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 | 6.940 us | 0.1364 us | 0.1675 us |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
new file mode 100755
index 0000000000..d49d1e3e51
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
@@ -0,0 +1,2 @@
+Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,EnvironmentVariables,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Mean,Error,StdDev
+DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,6.940 us,0.1364 us,0.1675 us
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html
new file mode 100755
index 0000000000..0f84d09546
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<meta charset='utf-8' />
+<title>JsonApiSerializer_Benchmarks</title>
+
+<style type="text/css">
+	table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
+	td, th { padding: 6px 13px; border: 1px solid #ddd; }
+	tr { background-color: #fff; border-top: 1px solid #ccc; }
+	tr:nth-child(even) { background: #f8f8f8; }
+</style>
+</head>
+<body>
+<pre><code>
+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
+</code></pre>
+<pre><code></code></pre>
+
+<table>
+<thead><tr><th>           Method</th><th>Mean</th><th>Error</th><th>StdDev</th>
+</tr>
+</thead><tbody><tr><td>DeserializeSimpleObject</td><td>6.940 us</td><td>0.1364 us</td><td>0.1675 us</td>
+</tr></tbody></table>
+</body>
+</html>
diff --git a/benchmarks/Program.cs b/benchmarks/Program.cs
index be5115f62c..2e552496c9 100644
--- a/benchmarks/Program.cs
+++ b/benchmarks/Program.cs
@@ -4,7 +4,8 @@
 namespace Benchmarks {
     class Program {
         static void Main(string[] args) {
-            var summary = BenchmarkRunner.Run<JsonApiDeserializer_Benchmarks>();
+            BenchmarkRunner.Run<JsonApiDeserializer_Benchmarks>();
+            BenchmarkRunner.Run<JsonApiSerializer_Benchmarks>();
         }
     }
 }
diff --git a/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs b/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
new file mode 100644
index 0000000000..0c87a3edfb
--- /dev/null
+++ b/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using BenchmarkDotNet.Attributes;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Internal.Generics;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Serialization;
+using JsonApiDotNetCore.Services;
+using Moq;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+
+namespace Benchmarks.Serialization {
+    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 contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<SimpleType>(TYPE_NAME);
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+
+            var documentBuilder = new DocumentBuilder(jsonApiContextMock.Object);
+            _jsonApiSerializer = new JsonApiSerializer(jsonApiContextMock.Object, documentBuilder);
+        }
+
+        [Benchmark]
+        public object DeserializeSimpleObject() => _jsonApiSerializer.Serialize(Content);
+
+        private class SimpleType : Identifiable {
+            [Attr("name")]
+            public string Name { get; set; }
+        }
+    }
+}

From 45dcb1258761f210d1fd14c8c0b623373319b3c4 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 14 Nov 2017 22:16:50 -0600
Subject: [PATCH 049/227] perf(*): only keep markdown benchmarks

---
 ...n.JsonApiDeserializer_Benchmarks-report-default.md | 11 +++++++++++
 ...on.JsonApiDeserializer_Benchmarks-report-github.md |  2 +-
 ...lization.JsonApiDeserializer_Benchmarks-report.csv |  2 +-
 ...ization.JsonApiDeserializer_Benchmarks-report.html |  2 +-
 ...ion.JsonApiSerializer_Benchmarks-report-default.md | 11 +++++++++++
 ...tion.JsonApiSerializer_Benchmarks-report-github.md |  2 +-
 ...ialization.JsonApiSerializer_Benchmarks-report.csv |  2 +-
 ...alization.JsonApiSerializer_Benchmarks-report.html |  2 +-
 .../Serialization/JsonApiDeserializer_Benchmarks.cs   |  2 ++
 .../Serialization/JsonApiSerializer_Benchmarks.cs     |  4 ++--
 10 files changed, 32 insertions(+), 8 deletions(-)
 create mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-default.md
 create mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-default.md

diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-default.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-default.md
new file mode 100755
index 0000000000..489c6588bf
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-default.md
@@ -0,0 +1,11 @@
+
+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.79 us | 0.5299 us | 0.4956 us |
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
index 2004bb0243..e87cadc3a7 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
@@ -10,4 +10,4 @@ Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
 ```
 |                  Method |     Mean |     Error |    StdDev |
 |------------------------ |---------:|----------:|----------:|
-| DeserializeSimpleObject | 27.34 us | 0.5458 us | 0.7472 us |
+| DeserializeSimpleObject | 27.79 us | 0.5299 us | 0.4956 us |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
index 230be6418f..80fffa3d41 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
@@ -1,2 +1,2 @@
 Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,EnvironmentVariables,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Mean,Error,StdDev
-DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,27.34 us,0.5458 us,0.7472 us
+DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,27.79 us,0.5299 us,0.4956 us
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
index e1906ca4e0..deb436dab9 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
@@ -24,7 +24,7 @@
 <table>
 <thead><tr><th>           Method</th><th>Mean</th><th>Error</th><th>StdDev</th>
 </tr>
-</thead><tbody><tr><td>DeserializeSimpleObject</td><td>27.34 us</td><td>0.5458 us</td><td>0.7472 us</td>
+</thead><tbody><tr><td>DeserializeSimpleObject</td><td>27.79 us</td><td>0.5299 us</td><td>0.4956 us</td>
 </tr></tbody></table>
 </body>
 </html>
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-default.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-default.md
new file mode 100755
index 0000000000..6e486a91d3
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-default.md
@@ -0,0 +1,11 @@
+
+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 | 7.032 us | 0.1101 us | 0.1030 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
index 66104fb0a2..e63c564dca 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
@@ -10,4 +10,4 @@ Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
 ```
 |                  Method |     Mean |     Error |    StdDev |
 |------------------------ |---------:|----------:|----------:|
-| DeserializeSimpleObject | 6.940 us | 0.1364 us | 0.1675 us |
+| DeserializeSimpleObject | 7.032 us | 0.1101 us | 0.1030 us |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
index d49d1e3e51..3279dabd04 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
@@ -1,2 +1,2 @@
 Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,EnvironmentVariables,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Mean,Error,StdDev
-DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,6.940 us,0.1364 us,0.1675 us
+DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,7.032 us,0.1101 us,0.1030 us
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html
index 0f84d09546..642ee73032 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html
@@ -24,7 +24,7 @@
 <table>
 <thead><tr><th>           Method</th><th>Mean</th><th>Error</th><th>StdDev</th>
 </tr>
-</thead><tbody><tr><td>DeserializeSimpleObject</td><td>6.940 us</td><td>0.1364 us</td><td>0.1675 us</td>
+</thead><tbody><tr><td>DeserializeSimpleObject</td><td>7.032 us</td><td>0.1101 us</td><td>0.1030 us</td>
 </tr></tbody></table>
 </body>
 </html>
diff --git a/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs b/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
index 9303b4d4c1..c490bee362 100644
--- a/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
+++ b/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Attributes.Exporters;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Internal.Generics;
@@ -12,6 +13,7 @@
 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 {
diff --git a/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs b/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
index 0c87a3edfb..e5de3cae79 100644
--- a/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
+++ b/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
@@ -1,6 +1,6 @@
-using System;
 using System.Collections.Generic;
 using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Attributes.Exporters;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Internal.Generics;
@@ -8,10 +8,10 @@
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
 using Moq;
-using Newtonsoft.Json;
 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();

From 4748e1620a9b59824e6638988d7ed3653ba577f5 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 26 Nov 2017 11:13:32 -0600
Subject: [PATCH 050/227] bench(QueryParser): add sort benchmarks

---
 benchmarks/.gitignore                         |  3 ++
 ...ry.QueryParser_Benchmarks-report-github.md | 15 ++++++
 benchmarks/Benchmarks.csproj                  |  1 +
 benchmarks/Program.cs                         |  2 +
 benchmarks/Query/QueryParser_Benchmarks.cs    | 48 +++++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
 create mode 100644 benchmarks/Query/QueryParser_Benchmarks.cs

diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore
index 0f552f400b..5a3c72cbbb 100644
--- a/benchmarks/.gitignore
+++ b/benchmarks/.gitignore
@@ -1,4 +1,7 @@
 _data/
+*-report-default.md
+*-report.csv
+*-report.html
 
 ## Ignore Visual Studio temporary files, build results, and
 ## files generated by popular Visual Studio add-ons.
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
new file mode 100755
index 0000000000..97fea375d6
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
@@ -0,0 +1,15 @@
+``` 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-HURVUO : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
+
+LaunchCount=3  TargetCount=20  WarmupCount=10  
+
+```
+|         Method |     Mean |     Error |    StdDev |
+|--------------- |---------:|----------:|----------:|
+|  AscendingSort | 3.146 us | 0.0326 us | 0.0709 us |
+| DescendingSort | 3.372 us | 0.1228 us | 0.2618 us |
diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj
index 107fd008c2..b5ff121826 100644
--- a/benchmarks/Benchmarks.csproj
+++ b/benchmarks/Benchmarks.csproj
@@ -3,6 +3,7 @@
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
+    <AssemblyName>Benchmarks</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
     <PackageReference Include="BenchmarkDotNet" Version="0.10.10" />
diff --git a/benchmarks/Program.cs b/benchmarks/Program.cs
index 2e552496c9..da4eaa2b50 100644
--- a/benchmarks/Program.cs
+++ b/benchmarks/Program.cs
@@ -1,4 +1,5 @@
 using BenchmarkDotNet.Running;
+using Benchmarks.Query;
 using Benchmarks.Serialization;
 
 namespace Benchmarks {
@@ -6,6 +7,7 @@ class Program {
         static void Main(string[] args) {
             BenchmarkRunner.Run<JsonApiDeserializer_Benchmarks>();
             BenchmarkRunner.Run<JsonApiSerializer_Benchmarks>();
+            BenchmarkRunner.Run<QueryParser_Benchmarks>();
         }
     }
 }
diff --git a/benchmarks/Query/QueryParser_Benchmarks.cs b/benchmarks/Query/QueryParser_Benchmarks.cs
new file mode 100644
index 0000000000..0edaee6cb5
--- /dev/null
+++ b/benchmarks/Query/QueryParser_Benchmarks.cs
@@ -0,0 +1,48 @@
+using System.Collections.Generic;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Attributes.Exporters;
+using BenchmarkDotNet.Attributes.Jobs;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Services;
+using Moq;
+
+namespace Benchmarks.Query {
+    [MarkdownExporter, SimpleJob(launchCount : 3, warmupCount : 10, targetCount : 20)]
+    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 controllerContextMock = new Mock<IControllerContext>();
+            controllerContextMock.Setup(m => m.RequestEntity).Returns(new ContextEntity {
+                Attributes = new List<AttrAttribute> {
+                    new AttrAttribute(ATTRIBUTE) {
+                        InternalAttributeName = ATTRIBUTE
+                    }
+                }
+            });
+            var options = new JsonApiOptions();
+            _queryParser = new BenchmarkFacade(controllerContextMock.Object, options);
+        }
+
+        [Benchmark]
+        public void AscendingSort() => _queryParser._ParseSortParameters(ASCENDING_SORT);
+
+        [Benchmark]
+        public void DescendingSort() => _queryParser._ParseSortParameters(DESCENDING_SORT);
+
+        // this facade allows us to expose and micro-benchmark protected methods
+        private class BenchmarkFacade : QueryParser {
+            public BenchmarkFacade(
+                IControllerContext controllerContext,
+                JsonApiOptions options) : base(controllerContext, options) { }
+
+            public void _ParseSortParameters(string value) => base.ParseSortParameters(value);
+        }
+    }
+}

From 78274c3c21b117f9c59b34ac659c2d2ecc1e04e6 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 26 Nov 2017 11:16:57 -0600
Subject: [PATCH 051/227] perf(QueryParser): improve sort parsing perf

AscendingSort: 30.9% improvement
DescendingSort: 20% improvement

BEFORE

          Method |     Mean |     Error |    StdDev|
--------------- |---------:|----------:|----------:|
  AscendingSort | 4.558 us | 0.2451 us | 0.6832 us |
 DescendingSort | 4.218 us | 0.1780 us | 0.4990 us |

AFTER

          Method |     Mean |     Error |    StdDev |
--------------- |---------:|----------:|----------:|
  AscendingSort | 3.146 us | 0.0326 us | 0.0709 us |
 DescendingSort | 3.372 us | 0.1228 us | 0.2618 us |
---
 src/JsonApiDotNetCore/Services/QueryParser.cs | 102 ++++++++----------
 1 file changed, 44 insertions(+), 58 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 297eb246a0..46f7a4e68a 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -9,63 +9,52 @@
 using JsonApiDotNetCore.Models;
 using Microsoft.AspNetCore.Http;
 
-namespace JsonApiDotNetCore.Services
-{
-    public interface IQueryParser
-    {
+namespace JsonApiDotNetCore.Services {
+    public interface IQueryParser {
         QuerySet Parse(IQueryCollection query);
     }
 
-    public class QueryParser : IQueryParser
-    {
+    public class QueryParser : IQueryParser {
         private readonly IControllerContext _controllerContext;
         private readonly JsonApiOptions _options;
 
         public QueryParser(
             IControllerContext controllerContext,
-            JsonApiOptions options)
-        {
+            JsonApiOptions options) {
             _controllerContext = controllerContext;
             _options = options;
         }
 
-        public virtual QuerySet Parse(IQueryCollection query)
-        {
+        public virtual QuerySet Parse(IQueryCollection query) {
             var querySet = new QuerySet();
-            var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>()?.QueryParams ?? QueryParams.None;
+            var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>() ? .QueryParams ?? QueryParams.None;
 
-            foreach (var pair in query)
-            {
-                if (pair.Key.StartsWith("filter"))
-                {
+            foreach (var pair in query) {
+                if (pair.Key.StartsWith("filter")) {
                     if (disabledQueries.HasFlag(QueryParams.Filter) == false)
                         querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
                     continue;
                 }
 
-                if (pair.Key.StartsWith("sort"))
-                {
+                if (pair.Key.StartsWith("sort")) {
                     if (disabledQueries.HasFlag(QueryParams.Sort) == false)
                         querySet.SortParameters = ParseSortParameters(pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith("include"))
-                {
+                if (pair.Key.StartsWith("include")) {
                     if (disabledQueries.HasFlag(QueryParams.Include) == false)
                         querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith("page"))
-                {
+                if (pair.Key.StartsWith("page")) {
                     if (disabledQueries.HasFlag(QueryParams.Page) == false)
                         querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith("fields"))
-                {
+                if (pair.Key.StartsWith("fields")) {
                     if (disabledQueries.HasFlag(QueryParams.Fields) == false)
                         querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value);
                     continue;
@@ -78,26 +67,24 @@ public virtual QuerySet Parse(IQueryCollection query)
             return querySet;
         }
 
-        protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
-        {
+        protected virtual List<FilterQuery> ParseFilterQuery(string key, string value) {
             // expected input = filter[id]=1
             // expected input = filter[id]=eq:1
             var queries = new List<FilterQuery>();
 
-            var propertyName = key.Split('[', ']')[1].ToProperCase();
+            var propertyName = key.Split('[', ']') [1].ToProperCase();
 
             var values = value.Split(',');
-            foreach (var val in values)
-            {
-                (var operation, var filterValue) = ParseFilterOperation(val);
+            foreach (var val in values) {
+                (var operation,
+                    var filterValue) = ParseFilterOperation(val);
                 queries.Add(new FilterQuery(propertyName, filterValue, operation));
             }
 
             return queries;
         }
 
-        protected virtual (string operation, string value) ParseFilterOperation(string value)
-        {
+        protected virtual(string operation, string value) ParseFilterOperation(string value) {
             if (value.Length < 3)
                 return (string.Empty, value);
 
@@ -116,13 +103,12 @@ protected virtual (string operation, string value) ParseFilterOperation(string v
             return (prefix, value);
         }
 
-        protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value)
-        {
+        protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value) {
             // expected input = page[size]=10
             //                  page[number]=1
             pageQuery = pageQuery ?? new PageQuery();
 
-            var propertyName = key.Split('[', ']')[1];
+            var propertyName = key.Split('[', ']') [1];
 
             if (propertyName == "size")
                 pageQuery.PageSize = Convert.ToInt32(value);
@@ -134,28 +120,31 @@ protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, stri
 
         // sort=id,name
         // sort=-id
-        protected virtual List<SortQuery> ParseSortParameters(string value)
-        {
+        protected virtual List<SortQuery> ParseSortParameters(string value) {
+            const char SORT_DELIMITER = ',';
+            const char DESCENDING_SORT_OPERATOR = '-';
+
             var sortParameters = new List<SortQuery>();
-            value.Split(',').ToList().ForEach(p =>
-            {
+            var sortSegments = value.Split(SORT_DELIMITER);
+            foreach (var sortSegment in sortSegments) {
+
+                var propertyName = sortSegment;
                 var direction = SortDirection.Ascending;
-                if (p[0] == '-')
-                {
+
+                if (sortSegment[0] == DESCENDING_SORT_OPERATOR) {
                     direction = SortDirection.Descending;
-                    p = p.Substring(1);
+                    propertyName = propertyName.Substring(1);
                 }
 
-                var attribute = GetAttribute(p.ToProperCase());
+                var attribute = GetAttribute(propertyName);
 
                 sortParameters.Add(new SortQuery(direction, attribute));
-            });
+            };
 
             return sortParameters;
         }
 
-        protected virtual List<string> ParseIncludedRelationships(string value)
-        {
+        protected virtual List<string> ParseIncludedRelationships(string value) {
             if (value.Contains("."))
                 throw new JsonApiException(400, "Deeply nested relationships are not supported");
 
@@ -164,10 +153,9 @@ protected virtual List<string> ParseIncludedRelationships(string value)
                 .ToList();
         }
 
-        protected virtual List<string> ParseFieldsQuery(string key, string value)
-        {
+        protected virtual List<string> ParseFieldsQuery(string key, string value) {
             // expected: fields[TYPE]=prop1,prop2
-            var typeName = key.Split('[', ']')[1];
+            var typeName = key.Split('[', ']') [1];
 
             var includedFields = new List<string> { "Id" };
 
@@ -175,8 +163,7 @@ protected virtual List<string> ParseFieldsQuery(string key, string value)
                 return includedFields;
 
             var fields = value.Split(',');
-            foreach (var field in fields)
-            {
+            foreach (var field in fields) {
                 var internalAttrName = _controllerContext.RequestEntity
                     .Attributes
                     .SingleOrDefault(attr => attr.PublicAttributeName == field)
@@ -187,12 +174,11 @@ protected virtual List<string> ParseFieldsQuery(string key, string value)
             return includedFields;
         }
 
-        protected virtual AttrAttribute GetAttribute(string propertyName)
-            => _controllerContext
-                .RequestEntity
-                .Attributes
-                .FirstOrDefault(attr =>
-                    string.Equals(attr.InternalAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
-                );
+        protected virtual AttrAttribute GetAttribute(string propertyName) => _controllerContext
+            .RequestEntity
+            .Attributes
+            .FirstOrDefault(attr =>
+                string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
+            );
     }
-}
\ No newline at end of file
+}

From 8d29d7e1467860a94bc9c3b1758e7060bf0336d0 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 26 Nov 2017 11:30:47 -0600
Subject: [PATCH 052/227] chore(benchmark-results): cleanup results

---
 ...ry.QueryParser_Benchmarks-report-github.md |  6 ++--
 ...iDeserializer_Benchmarks-report-default.md | 11 -------
 ...piDeserializer_Benchmarks-report-github.md |  2 +-
 ....JsonApiDeserializer_Benchmarks-report.csv |  2 --
 ...JsonApiDeserializer_Benchmarks-report.html | 30 -------------------
 ...ApiSerializer_Benchmarks-report-default.md | 11 -------
 ...nApiSerializer_Benchmarks-report-github.md |  2 +-
 ...on.JsonApiSerializer_Benchmarks-report.csv |  2 --
 ...n.JsonApiSerializer_Benchmarks-report.html | 30 -------------------
 .../JsonApiSerializer_Benchmarks.cs           |  2 +-
 10 files changed, 6 insertions(+), 92 deletions(-)
 delete mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-default.md
 delete mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
 delete mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
 delete mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-default.md
 delete mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
 delete mode 100755 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html

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
index 97fea375d6..324281fa40 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
@@ -4,12 +4,12 @@ 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-HURVUO : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
+  Job-ROPOBW : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
 
 LaunchCount=3  TargetCount=20  WarmupCount=10  
 
 ```
 |         Method |     Mean |     Error |    StdDev |
 |--------------- |---------:|----------:|----------:|
-|  AscendingSort | 3.146 us | 0.0326 us | 0.0709 us |
-| DescendingSort | 3.372 us | 0.1228 us | 0.2618 us |
+|  AscendingSort | 3.101 us | 0.0298 us | 0.0636 us |
+| DescendingSort | 3.195 us | 0.0297 us | 0.0632 us |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-default.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-default.md
deleted file mode 100755
index 489c6588bf..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-default.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-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.79 us | 0.5299 us | 0.4956 us |
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
index e87cadc3a7..d8571f9644 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
@@ -10,4 +10,4 @@ Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
 ```
 |                  Method |     Mean |     Error |    StdDev |
 |------------------------ |---------:|----------:|----------:|
-| DeserializeSimpleObject | 27.79 us | 0.5299 us | 0.4956 us |
+| DeserializeSimpleObject | 26.37 us | 0.4458 us | 0.4170 us |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
deleted file mode 100755
index 80fffa3d41..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,EnvironmentVariables,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Mean,Error,StdDev
-DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,27.79 us,0.5299 us,0.4956 us
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
deleted file mode 100755
index deb436dab9..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<html lang='en'>
-<head>
-<meta charset='utf-8' />
-<title>JsonApiDeserializer_Benchmarks</title>
-
-<style type="text/css">
-	table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
-	td, th { padding: 6px 13px; border: 1px solid #ddd; }
-	tr { background-color: #fff; border-top: 1px solid #ccc; }
-	tr:nth-child(even) { background: #f8f8f8; }
-</style>
-</head>
-<body>
-<pre><code>
-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
-</code></pre>
-<pre><code></code></pre>
-
-<table>
-<thead><tr><th>           Method</th><th>Mean</th><th>Error</th><th>StdDev</th>
-</tr>
-</thead><tbody><tr><td>DeserializeSimpleObject</td><td>27.79 us</td><td>0.5299 us</td><td>0.4956 us</td>
-</tr></tbody></table>
-</body>
-</html>
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-default.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-default.md
deleted file mode 100755
index 6e486a91d3..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-default.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-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 | 7.032 us | 0.1101 us | 0.1030 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
index e63c564dca..4671d6b3af 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
@@ -10,4 +10,4 @@ Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
 ```
 |                  Method |     Mean |     Error |    StdDev |
 |------------------------ |---------:|----------:|----------:|
-| DeserializeSimpleObject | 7.032 us | 0.1101 us | 0.1030 us |
+| DeserializeSimpleObject | 7.135 us | 0.1401 us | 0.1439 us |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
deleted file mode 100755
index 3279dabd04..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,RemoveOutliers,Affinity,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,EnvironmentVariables,Toolchain,InvocationCount,IterationTime,LaunchCount,RunStrategy,TargetCount,UnrollFactor,WarmupCount,Mean,Error,StdDev
-DeserializeSimpleObject,Default,False,Default,Default,Default,Default,Default,Default,0,RyuJit,X64,Core,False,True,False,True,False,False,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,16,Default,7.032 us,0.1101 us,0.1030 us
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html
deleted file mode 100755
index 642ee73032..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<html lang='en'>
-<head>
-<meta charset='utf-8' />
-<title>JsonApiSerializer_Benchmarks</title>
-
-<style type="text/css">
-	table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
-	td, th { padding: 6px 13px; border: 1px solid #ddd; }
-	tr { background-color: #fff; border-top: 1px solid #ccc; }
-	tr:nth-child(even) { background: #f8f8f8; }
-</style>
-</head>
-<body>
-<pre><code>
-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
-</code></pre>
-<pre><code></code></pre>
-
-<table>
-<thead><tr><th>           Method</th><th>Mean</th><th>Error</th><th>StdDev</th>
-</tr>
-</thead><tbody><tr><td>DeserializeSimpleObject</td><td>7.032 us</td><td>0.1101 us</td><td>0.1030 us</td>
-</tr></tbody></table>
-</body>
-</html>
diff --git a/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs b/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
index e5de3cae79..3d5ef7c001 100644
--- a/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
+++ b/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
@@ -39,7 +39,7 @@ public JsonApiSerializer_Benchmarks() {
         }
 
         [Benchmark]
-        public object DeserializeSimpleObject() => _jsonApiSerializer.Serialize(Content);
+        public object SerializeSimpleObject() => _jsonApiSerializer.Serialize(Content);
 
         private class SimpleType : Identifiable {
             [Attr("name")]

From 15a9830f9e0cc9ea51b0051441457bc8a77047e5 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 26 Nov 2017 15:40:04 -0600
Subject: [PATCH 053/227] feat(FilterQuery / QueryAccessor): use public
 attribute names for keys

Closes #197
---
 .../Internal/Query/AttrFilterQuery.cs         | 20 ++++++++--------
 .../Internal/Query/FilterQuery.cs             | 14 +++++++----
 .../Services/QueryAccessor.cs                 | 23 +++++++++++++++----
 src/JsonApiDotNetCore/Services/QueryParser.cs |  4 +++-
 4 files changed, 40 insertions(+), 21 deletions(-)

diff --git a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
index 8af2fe95e1..74db2b342e 100644
--- a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Linq;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
@@ -9,14 +10,14 @@ public class AttrFilterQuery : BaseFilterQuery
         private readonly IJsonApiContext _jsonApiContext;
 
         public AttrFilterQuery(
-            IJsonApiContext jsonApiCopntext,
+            IJsonApiContext jsonApiContext,
             FilterQuery filterQuery)
         {
-            _jsonApiContext = jsonApiCopntext;
+            _jsonApiContext = jsonApiContext;
 
-            var attribute = GetAttribute(filterQuery.Key);
+            var attribute = GetAttribute(filterQuery.Attribute);
 
-            FilteredAttribute = attribute ?? throw new JsonApiException(400, $"{filterQuery.Key} is not a valid property.");
+            FilteredAttribute = attribute ?? throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
             PropertyValue = filterQuery.Value;
             FilterOperation = GetFilterOperation(filterQuery.Operation);
         }
@@ -25,12 +26,9 @@ public AttrFilterQuery(
         public string PropertyValue { get; set; }
         public FilterOperations FilterOperation { get; set; }
 
-        private AttrAttribute GetAttribute(string propertyName)
-        {
-            return _jsonApiContext.RequestEntity.Attributes
-                .FirstOrDefault(attr =>
-                    attr.InternalAttributeName.ToLower() == propertyName.ToLower()
+        private AttrAttribute GetAttribute(string attribute) =>  
+            _jsonApiContext.RequestEntity.Attributes.FirstOrDefault(
+                attr => string.Equals(attr.PublicAttributeName, attribute, StringComparison.OrdinalIgnoreCase)
             );
-        }
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Internal/Query/FilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/FilterQuery.cs
index 7f4f1a40c6..dd72e827ff 100644
--- a/src/JsonApiDotNetCore/Internal/Query/FilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/FilterQuery.cs
@@ -1,17 +1,23 @@
+using System;
+using JsonApiDotNetCore.Extensions;
+
 namespace JsonApiDotNetCore.Internal.Query
 {
     public class FilterQuery
     {
-        public FilterQuery(string key, string value, string operation)
+        public FilterQuery(string attribute, string value, string operation)
         {
-            Key = key;
+            Attribute = attribute;
+            Key = attribute.ToProperCase();
             Value = value;
             Operation = operation;
         }
         
+        [Obsolete("Key has been replaced by '" + nameof(Attribute) + "'. Members should be located by their public name, not by coercing the provided value to the internal name.")]
         public string Key { get; set; }
+        public string Attribute { get; }
         public string Value { get; set; }
         public string Operation { get; set; }
-        public bool IsAttributeOfRelationship => Key.Contains(".");
+        public bool IsAttributeOfRelationship => Attribute.Contains(".");
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Services/QueryAccessor.cs b/src/JsonApiDotNetCore/Services/QueryAccessor.cs
index 09942d4031..63b91ed239 100644
--- a/src/JsonApiDotNetCore/Services/QueryAccessor.cs
+++ b/src/JsonApiDotNetCore/Services/QueryAccessor.cs
@@ -61,9 +61,22 @@ public bool TryGetValue<T>(string key, out T value)
             }
         }
 
-        private string GetFilterValue(string key) => _jsonApiContext.QuerySet
-            .Filters
-            .FirstOrDefault(f => string.Equals(f.Key, key, StringComparison.OrdinalIgnoreCase))
-            ?.Value;
+        private string GetFilterValue(string key) {
+            var publicValue = _jsonApiContext.QuerySet.Filters
+                .FirstOrDefault(f => string.Equals(f.Attribute, key, StringComparison.OrdinalIgnoreCase))?.Value;
+            
+            if(publicValue != null) 
+                return publicValue;
+            
+            var internalValue = _jsonApiContext.QuerySet.Filters
+                .FirstOrDefault(f => string.Equals(f.Key, key, StringComparison.OrdinalIgnoreCase))?.Value;
+            
+            if(internalValue != null) {
+                _logger.LogWarning("Locating filters by the internal propterty name is deprecated. You should use the public attribute name instead.");
+                return publicValue;
+            }
+
+            return null;
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 46f7a4e68a..1e956d64f4 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -18,6 +18,8 @@ public class QueryParser : IQueryParser {
         private readonly IControllerContext _controllerContext;
         private readonly JsonApiOptions _options;
 
+        private const char OPEN_BRACKET = '[';
+        private const char CLOSE_BRACKET = ']';
         public QueryParser(
             IControllerContext controllerContext,
             JsonApiOptions options) {
@@ -72,7 +74,7 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value) {
             // expected input = filter[id]=eq:1
             var queries = new List<FilterQuery>();
 
-            var propertyName = key.Split('[', ']') [1].ToProperCase();
+            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
 
             var values = value.Split(',');
             foreach (var val in values) {

From cb20ff405cf24a835e3c99bee690895455c82ba9 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 26 Nov 2017 15:56:23 -0600
Subject: [PATCH 054/227] perf(QueryParser): constants instead of inline
 strings

---
 src/JsonApiDotNetCore/Services/QueryParser.cs | 74 ++++++++++++-------
 1 file changed, 46 insertions(+), 28 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 1e956d64f4..8f721aef62 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -3,7 +3,6 @@
 using System.Linq;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Controllers;
-using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
@@ -18,8 +17,17 @@ public class QueryParser : IQueryParser {
         private readonly IControllerContext _controllerContext;
         private readonly JsonApiOptions _options;
 
+        private const string FILTER = "filter";
+        private const string SORT = "sort";
+        private const string INCLUDE = "include";
+        private const string PAGE = "page";
+        private const string FIELDS = "fields";
         private const char OPEN_BRACKET = '[';
         private const char CLOSE_BRACKET = ']';
+        private const char COMMA = ',';
+        private const char COLON = ':';
+        private const string COLON_STR = ":";
+
         public QueryParser(
             IControllerContext controllerContext,
             JsonApiOptions options) {
@@ -32,31 +40,31 @@ public virtual QuerySet Parse(IQueryCollection query) {
             var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>() ? .QueryParams ?? QueryParams.None;
 
             foreach (var pair in query) {
-                if (pair.Key.StartsWith("filter")) {
+                if (pair.Key.StartsWith(FILTER)) {
                     if (disabledQueries.HasFlag(QueryParams.Filter) == false)
                         querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
                     continue;
                 }
 
-                if (pair.Key.StartsWith("sort")) {
+                if (pair.Key.StartsWith(SORT)) {
                     if (disabledQueries.HasFlag(QueryParams.Sort) == false)
                         querySet.SortParameters = ParseSortParameters(pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith("include")) {
+                if (pair.Key.StartsWith(INCLUDE)) {
                     if (disabledQueries.HasFlag(QueryParams.Include) == false)
                         querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith("page")) {
+                if (pair.Key.StartsWith(PAGE)) {
                     if (disabledQueries.HasFlag(QueryParams.Page) == false)
                         querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith("fields")) {
+                if (pair.Key.StartsWith(FIELDS)) {
                     if (disabledQueries.HasFlag(QueryParams.Fields) == false)
                         querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value);
                     continue;
@@ -76,10 +84,9 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value) {
 
             var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
 
-            var values = value.Split(',');
+            var values = value.Split(COMMA);
             foreach (var val in values) {
-                (var operation,
-                    var filterValue) = ParseFilterOperation(val);
+                (var operation, var filterValue) = ParseFilterOperation(val);
                 queries.Add(new FilterQuery(propertyName, filterValue, operation));
             }
 
@@ -90,7 +97,7 @@ protected virtual(string operation, string value) ParseFilterOperation(string va
             if (value.Length < 3)
                 return (string.Empty, value);
 
-            var operation = value.Split(':');
+            var operation = value.Split(COLON);
 
             if (operation.Length == 1)
                 return (string.Empty, value);
@@ -100,7 +107,7 @@ protected virtual(string operation, string value) ParseFilterOperation(string va
                 return (string.Empty, value);
 
             var prefix = operation[0];
-            value = string.Join(":", operation.Skip(1));
+            value = string.Join(COLON_STR, operation.Skip(1));
 
             return (prefix, value);
         }
@@ -110,11 +117,14 @@ protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, stri
             //                  page[number]=1
             pageQuery = pageQuery ?? new PageQuery();
 
-            var propertyName = key.Split('[', ']') [1];
+            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
+
+            const string SIZE = "size";
+            const string NUMBER = "number";
 
-            if (propertyName == "size")
+            if (propertyName == SIZE)
                 pageQuery.PageSize = Convert.ToInt32(value);
-            else if (propertyName == "number")
+            else if (propertyName == NUMBER)
                 pageQuery.PageOffset = Convert.ToInt32(value);
 
             return pageQuery;
@@ -123,11 +133,11 @@ protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, stri
         // sort=id,name
         // sort=-id
         protected virtual List<SortQuery> ParseSortParameters(string value) {
-            const char SORT_DELIMITER = ',';
+            var sortParameters = new List<SortQuery>();
+
             const char DESCENDING_SORT_OPERATOR = '-';
+            var sortSegments = value.Split(COMMA);
 
-            var sortParameters = new List<SortQuery>();
-            var sortSegments = value.Split(SORT_DELIMITER);
             foreach (var sortSegment in sortSegments) {
 
                 var propertyName = sortSegment;
@@ -147,24 +157,26 @@ protected virtual List<SortQuery> ParseSortParameters(string value) {
         }
 
         protected virtual List<string> ParseIncludedRelationships(string value) {
-            if (value.Contains("."))
+            const string NESTED_DELIMITER = ".";
+            if (value.Contains(NESTED_DELIMITER))
                 throw new JsonApiException(400, "Deeply nested relationships are not supported");
 
             return value
-                .Split(',')
+                .Split(COMMA)
                 .ToList();
         }
 
         protected virtual List<string> ParseFieldsQuery(string key, string value) {
             // expected: fields[TYPE]=prop1,prop2
-            var typeName = key.Split('[', ']') [1];
+            var typeName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
 
-            var includedFields = new List<string> { "Id" };
+            const string ID = "Id";
+            var includedFields = new List<string> { ID };
 
             if (typeName != _controllerContext.RequestEntity.EntityName)
                 return includedFields;
 
-            var fields = value.Split(',');
+            var fields = value.Split(COMMA);
             foreach (var field in fields) {
                 var internalAttrName = _controllerContext.RequestEntity
                     .Attributes
@@ -176,11 +188,17 @@ protected virtual List<string> ParseFieldsQuery(string key, string value) {
             return includedFields;
         }
 
-        protected virtual AttrAttribute GetAttribute(string propertyName) => _controllerContext
-            .RequestEntity
-            .Attributes
-            .FirstOrDefault(attr =>
-                string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
-            );
+        protected virtual AttrAttribute GetAttribute(string propertyName) {
+            try {
+                return _controllerContext
+                    .RequestEntity
+                    .Attributes
+                    .Single(attr =>
+                        string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
+                    );
+            } catch (InvalidOperationException e) {
+                throw new JsonApiException(400, $"Attribute '{propertyName}' does not exist on resource '{_controllerContext.RequestEntity.EntityName}'");
+            }
+        }
     }
 }

From a8831b2ef0d1453195cc0a19f9b875316b071b4d Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 26 Nov 2017 15:56:34 -0600
Subject: [PATCH 055/227] bench(*): run new benchmarks

---
 ...ry.QueryParser_Benchmarks-report-github.md | 11 +++++-----
 ...piDeserializer_Benchmarks-report-github.md |  2 +-
 ...nApiSerializer_Benchmarks-report-github.md |  6 +++---
 benchmarks/Query/QueryParser_Benchmarks.cs    | 21 +++++++++++++++++++
 4 files changed, 31 insertions(+), 9 deletions(-)

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
index 324281fa40..4678b3141e 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
@@ -4,12 +4,13 @@ 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-ROPOBW : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
+  Job-OWXJBF : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
 
 LaunchCount=3  TargetCount=20  WarmupCount=10  
 
 ```
-|         Method |     Mean |     Error |    StdDev |
-|--------------- |---------:|----------:|----------:|
-|  AscendingSort | 3.101 us | 0.0298 us | 0.0636 us |
-| DescendingSort | 3.195 us | 0.0297 us | 0.0632 us |
+|         Method |         Mean |      Error |      StdDev |       Median |
+|--------------- |-------------:|-----------:|------------:|-------------:|
+|  AscendingSort |     4.451 us |  1.5230 us |   3.2457 us |     3.305 us |
+| DescendingSort |     3.287 us |  0.0307 us |   0.0673 us |     3.263 us |
+|   ComplexQuery | 1,973.029 us | 67.5600 us | 143.9759 us | 1,952.663 us |
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
index d8571f9644..6c8c3f2905 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
@@ -10,4 +10,4 @@ Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
 ```
 |                  Method |     Mean |     Error |    StdDev |
 |------------------------ |---------:|----------:|----------:|
-| DeserializeSimpleObject | 26.37 us | 0.4458 us | 0.4170 us |
+| 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
index 4671d6b3af..f86bf0faa9 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
@@ -8,6 +8,6 @@ Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
 
 
 ```
-|                  Method |     Mean |     Error |    StdDev |
-|------------------------ |---------:|----------:|----------:|
-| DeserializeSimpleObject | 7.135 us | 0.1401 us | 0.1439 us |
+|                Method |     Mean |     Error |    StdDev |
+|---------------------- |---------:|----------:|----------:|
+| SerializeSimpleObject | 7.195 us | 0.1436 us | 0.1816 us |
diff --git a/benchmarks/Query/QueryParser_Benchmarks.cs b/benchmarks/Query/QueryParser_Benchmarks.cs
index 0edaee6cb5..8a077de2bf 100644
--- a/benchmarks/Query/QueryParser_Benchmarks.cs
+++ b/benchmarks/Query/QueryParser_Benchmarks.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections.Generic;
 using BenchmarkDotNet.Attributes;
 using BenchmarkDotNet.Attributes.Exporters;
@@ -6,6 +7,8 @@
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Http.Internal;
+using Microsoft.Extensions.Primitives;
 using Moq;
 
 namespace Benchmarks.Query {
@@ -36,6 +39,24 @@ public QueryParser_Benchmarks() {
         [Benchmark]
         public void DescendingSort() => _queryParser._ParseSortParameters(DESCENDING_SORT);
 
+        [Benchmark]
+        public void ComplexQuery() => Run(100, () => _queryParser.Parse(
+            new QueryCollection(
+                new Dictionary<string, StringValues> { 
+                    { $"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 : QueryParser {
             public BenchmarkFacade(

From 0e6778fa1aa6f208350530db3994ebd4390330f7 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 3 Dec 2017 15:14:23 -0600
Subject: [PATCH 056/227] feat(*): add constants for Content-Type

---
 ...uery.QueryParser_Benchmarks-report-github.md | 12 ++++++------
 benchmarks/Program.cs                           |  9 ++++++---
 benchmarks/Query/QueryParser_Benchmarks.cs      |  2 +-
 .../Formatters/JsonApiInputFormatter.cs         |  3 ++-
 .../Formatters/JsonApiOutputFormatter.cs        |  3 ++-
 .../Formatters/JsonApiWriter.cs                 |  7 ++++---
 src/JsonApiDotNetCore/Internal/Constants.cs     |  8 ++++++++
 .../Internal/JsonApiExceptionFactory.cs         |  7 +++++--
 .../Internal/Query/BaseFilterQuery.cs           |  4 ++--
 .../Internal/Query/RelatedAttrFilterQuery.cs    |  9 +++++----
 .../Middleware/RequestMiddleware.cs             |  5 +++--
 src/JsonApiDotNetCore/Models/DocumentBase.cs    | 17 +++--------------
 12 files changed, 47 insertions(+), 39 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Internal/Constants.cs

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
index 4678b3141e..b3ebd8a29c 100755
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
@@ -4,13 +4,13 @@ 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-OWXJBF : .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 |       Median |
-|--------------- |-------------:|-----------:|------------:|-------------:|
-|  AscendingSort |     4.451 us |  1.5230 us |   3.2457 us |     3.305 us |
-| DescendingSort |     3.287 us |  0.0307 us |   0.0673 us |     3.263 us |
-|   ComplexQuery | 1,973.029 us | 67.5600 us | 143.9759 us | 1,952.663 us |
+|         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/Program.cs b/benchmarks/Program.cs
index da4eaa2b50..7665d5fb97 100644
--- a/benchmarks/Program.cs
+++ b/benchmarks/Program.cs
@@ -5,9 +5,12 @@
 namespace Benchmarks {
     class Program {
         static void Main(string[] args) {
-            BenchmarkRunner.Run<JsonApiDeserializer_Benchmarks>();
-            BenchmarkRunner.Run<JsonApiSerializer_Benchmarks>();
-            BenchmarkRunner.Run<QueryParser_Benchmarks>();
+            var switcher = new BenchmarkSwitcher(new[] {
+                typeof(JsonApiDeserializer_Benchmarks),
+                typeof(JsonApiSerializer_Benchmarks),
+                typeof(QueryParser_Benchmarks)
+            });
+            switcher.Run(args);
         }
     }
 }
diff --git a/benchmarks/Query/QueryParser_Benchmarks.cs b/benchmarks/Query/QueryParser_Benchmarks.cs
index 8a077de2bf..61fe3b1bc2 100644
--- a/benchmarks/Query/QueryParser_Benchmarks.cs
+++ b/benchmarks/Query/QueryParser_Benchmarks.cs
@@ -12,7 +12,7 @@
 using Moq;
 
 namespace Benchmarks.Query {
-    [MarkdownExporter, SimpleJob(launchCount : 3, warmupCount : 10, targetCount : 20)]
+    [MarkdownExporter, SimpleJob(launchCount : 3, warmupCount : 10, targetCount : 20), MemoryDiagnoser]
     public class QueryParser_Benchmarks {
         private readonly BenchmarkFacade _queryParser;
 
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
index 12e57deadf..f556b7433d 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiInputFormatter.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Internal;
 using Microsoft.AspNetCore.Mvc.Formatters;
 using Microsoft.Extensions.DependencyInjection;
 
@@ -14,7 +15,7 @@ public bool CanRead(InputFormatterContext context)
 
             var contentTypeString = context.HttpContext.Request.ContentType;
 
-            return contentTypeString == "application/vnd.api+json";
+            return contentTypeString == Constants.ContentType;
         }
 
         public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOutputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOutputFormatter.cs
index 2431055d1d..b456932fc5 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOutputFormatter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiOutputFormatter.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Internal;
 using Microsoft.AspNetCore.Mvc.Formatters;
 using Microsoft.Extensions.DependencyInjection;
 
@@ -14,7 +15,7 @@ public bool CanWriteResult(OutputFormatterCanWriteContext context)
 
             var contentTypeString = context.HttpContext.Request.ContentType;
 
-            return string.IsNullOrEmpty(contentTypeString) || contentTypeString == "application/vnd.api+json";
+            return string.IsNullOrEmpty(contentTypeString) || contentTypeString == Constants.ContentType;
         }
 
         public async Task WriteAsync(OutputFormatterWriteContext context)
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs
index 730a88f13e..d644def66d 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs
@@ -13,7 +13,8 @@ public class JsonApiWriter : IJsonApiWriter
         private readonly ILogger<JsonApiWriter> _logger;
         private readonly IJsonApiSerializer _serializer;
 
-        public JsonApiWriter(IJsonApiSerializer serializer, 
+        public JsonApiWriter(
+            IJsonApiSerializer serializer, 
             ILoggerFactory loggerFactory)
         {
             _serializer = serializer;
@@ -30,7 +31,7 @@ public async Task WriteAsync(OutputFormatterWriteContext context)
             var response = context.HttpContext.Response;
             using (var writer = context.WriterFactory(response.Body, Encoding.UTF8))
             {
-                response.ContentType = "application/vnd.api+json";
+                response.ContentType = Constants.ContentType;
                 string responseContent;
                 try
                 {
@@ -55,4 +56,4 @@ private string GetResponseBody(object responseObject)
             return _serializer.Serialize(responseObject);
         }        
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Internal/Constants.cs b/src/JsonApiDotNetCore/Internal/Constants.cs
new file mode 100644
index 0000000000..750d94ba07
--- /dev/null
+++ b/src/JsonApiDotNetCore/Internal/Constants.cs
@@ -0,0 +1,8 @@
+namespace JsonApiDotNetCore.Internal
+{
+    public static class Constants
+    {
+        public const string AcceptHeader = "Accept";
+        public const string ContentType = "application/vnd.api+json";
+    }
+}
diff --git a/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs b/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
index 42f3037f89..36b4969b1d 100644
--- a/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
@@ -5,14 +5,17 @@ namespace JsonApiDotNetCore.Internal
 {
     public static class JsonApiExceptionFactory
     {
+        private const string JsonApiException = nameof(JsonApiException);
+        private const string InvalidCastException = nameof(InvalidCastException);
+
         public static JsonApiException GetException(Exception exception)
         {
             var exceptionType = exception.GetType().ToString().Split('.').Last();
             switch(exceptionType)
             {
-                case "JsonApiException":
+                case JsonApiException:
                     return (JsonApiException)exception;
-                case "InvalidCastException":
+                case InvalidCastException:
                     return new JsonApiException(409, exception.Message);
                 default:
                     return new JsonApiException(500, exception.Message, GetExceptionDetail(exception.InnerException));
diff --git a/src/JsonApiDotNetCore/Internal/Query/BaseFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/BaseFilterQuery.cs
index 527b842ca8..1c43d84254 100644
--- a/src/JsonApiDotNetCore/Internal/Query/BaseFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/BaseFilterQuery.cs
@@ -8,10 +8,10 @@ protected FilterOperations GetFilterOperation(string prefix)
         {
             if (prefix.Length == 0) return FilterOperations.eq;
 
-            if (!Enum.TryParse(prefix, out FilterOperations opertion))
+            if (Enum.TryParse(prefix, out FilterOperations opertion) == false)
                 throw new JsonApiException(400, $"Invalid filter prefix '{prefix}'");
 
             return opertion;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
index dc633c5302..3b249c176c 100644
--- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Linq;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
@@ -14,7 +15,7 @@ public RelatedAttrFilterQuery(
         {
             _jsonApiContext = jsonApiCopntext;
 
-            var relationshipArray = filterQuery.Key.Split('.');
+            var relationshipArray = filterQuery.Attribute.Split('.');
 
             var relationship = GetRelationship(relationshipArray[0]);
             if (relationship == null)
@@ -36,14 +37,14 @@ public RelatedAttrFilterQuery(
         private RelationshipAttribute GetRelationship(string propertyName)
         {
             return _jsonApiContext.RequestEntity.Relationships
-              .FirstOrDefault(r => r.InternalRelationshipName.ToLower() == propertyName.ToLower());
+              .FirstOrDefault(r => string.Equals(r.PublicRelationshipName, propertyName, StringComparison.OrdinalIgnoreCase));
         }
 
         private AttrAttribute GetAttribute(RelationshipAttribute relationship, string attribute)
         {
             var relatedContextExntity = _jsonApiContext.ContextGraph.GetContextEntity(relationship.Type);
             return relatedContextExntity.Attributes
-              .FirstOrDefault(a => a.InternalAttributeName.ToLower() == attribute.ToLower());
+              .FirstOrDefault(a => string.Equals(a.PublicAttributeName, attribute, StringComparison.OrdinalIgnoreCase));
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
index 670def21d6..6e2612c9a6 100644
--- a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
+++ b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
@@ -1,4 +1,5 @@
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Internal;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Primitives;
 
@@ -37,7 +38,7 @@ private static bool IsValidContentTypeHeader(HttpContext context)
 
         private static bool IsValidAcceptHeader(HttpContext context)
         {
-            if (context.Request.Headers.TryGetValue("Accept", out StringValues acceptHeaders) == false)
+            if (context.Request.Headers.TryGetValue(Constants.AcceptHeader, out StringValues acceptHeaders) == false)
                 return true;
 
             foreach (var acceptHeader in acceptHeaders)
@@ -54,7 +55,7 @@ private static bool IsValidAcceptHeader(HttpContext context)
         private static bool ContainsMediaTypeParameters(string mediaType)
         {
             var mediaTypeArr = mediaType.Split(';');
-            return (mediaTypeArr[0] == "application/vnd.api+json" && mediaTypeArr.Length == 2);
+            return (mediaTypeArr[0] ==  Constants.ContentType && mediaTypeArr.Length == 2);
         }
 
         private static void FlushResponse(HttpContext context, int statusCode)
diff --git a/src/JsonApiDotNetCore/Models/DocumentBase.cs b/src/JsonApiDotNetCore/Models/DocumentBase.cs
index 1cb31595ec..df51301c20 100644
--- a/src/JsonApiDotNetCore/Models/DocumentBase.cs
+++ b/src/JsonApiDotNetCore/Models/DocumentBase.cs
@@ -15,19 +15,8 @@ public class DocumentBase
         public Dictionary<string, object> Meta { get; set; }
 
         // http://www.newtonsoft.com/json/help/html/ConditionalProperties.htm
-        public bool ShouldSerializeIncluded()
-        {
-            return (Included != null);
-        }
-
-        public bool ShouldSerializeMeta()
-        {
-            return (Meta != null);
-        }
-
-        public bool ShouldSerializeLinks()
-        {
-            return (Links != null);
-        }
+        public bool ShouldSerializeIncluded() => (Included != null);
+        public bool ShouldSerializeMeta() => (Meta != null);
+        public bool ShouldSerializeLinks() => (Links != null);
     }
 }

From a26990235d897fde7cc6a9fdee047334405eaad1 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 3 Dec 2017 15:18:10 -0600
Subject: [PATCH 057/227] fix(queryParser): remove access to obsolete key

---
 src/JsonApiDotNetCore/Services/QueryAccessor.cs |  2 +-
 src/JsonApiDotNetCore/Services/QueryParser.cs   |  2 +-
 test/UnitTests/Services/QueryParser_Tests.cs    | 10 +++++-----
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/QueryAccessor.cs b/src/JsonApiDotNetCore/Services/QueryAccessor.cs
index 63b91ed239..41bc64151b 100644
--- a/src/JsonApiDotNetCore/Services/QueryAccessor.cs
+++ b/src/JsonApiDotNetCore/Services/QueryAccessor.cs
@@ -69,7 +69,7 @@ private string GetFilterValue(string key) {
                 return publicValue;
             
             var internalValue = _jsonApiContext.QuerySet.Filters
-                .FirstOrDefault(f => string.Equals(f.Key, key, StringComparison.OrdinalIgnoreCase))?.Value;
+                .FirstOrDefault(f => string.Equals(f.Attribute, key, StringComparison.OrdinalIgnoreCase))?.Value;
             
             if(internalValue != null) {
                 _logger.LogWarning("Locating filters by the internal propterty name is deprecated. You should use the public attribute name instead.");
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 8f721aef62..47f9efa631 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -197,7 +197,7 @@ protected virtual AttrAttribute GetAttribute(string propertyName) {
                         string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
                     );
             } catch (InvalidOperationException e) {
-                throw new JsonApiException(400, $"Attribute '{propertyName}' does not exist on resource '{_controllerContext.RequestEntity.EntityName}'");
+                throw new JsonApiException(400, $"Attribute '{propertyName}' does not exist on resource '{_controllerContext.RequestEntity.EntityName}'", e);
             }
         }
     }
diff --git a/test/UnitTests/Services/QueryParser_Tests.cs b/test/UnitTests/Services/QueryParser_Tests.cs
index a64c5b3692..abe5d75568 100644
--- a/test/UnitTests/Services/QueryParser_Tests.cs
+++ b/test/UnitTests/Services/QueryParser_Tests.cs
@@ -43,7 +43,7 @@ public void Can_Build_Filters()
             var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
-            Assert.Equal("value", querySet.Filters.Single(f => f.Key == "Key").Value);
+            Assert.Equal("value", querySet.Filters.Single(f => f.Attribute == "key").Value);
         }
 
         [Fact]
@@ -69,8 +69,8 @@ public void Filters_Properly_Parses_DateTime_With_Operation()
             var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
-            Assert.Equal(dt, querySet.Filters.Single(f => f.Key == "Key").Value);
-            Assert.Equal("le", querySet.Filters.Single(f => f.Key == "Key").Operation);
+            Assert.Equal(dt, querySet.Filters.Single(f => f.Attribute == "key").Value);
+            Assert.Equal("le", querySet.Filters.Single(f => f.Attribute == "key").Operation);
         }
 
         [Fact]
@@ -96,8 +96,8 @@ public void Filters_Properly_Parses_DateTime_Without_Operation()
             var querySet = queryParser.Parse(_queryCollectionMock.Object);
 
             // assert
-            Assert.Equal(dt, querySet.Filters.Single(f => f.Key == "Key").Value);
-            Assert.Equal(string.Empty, querySet.Filters.Single(f => f.Key == "Key").Operation);
+            Assert.Equal(dt, querySet.Filters.Single(f => f.Attribute == "key").Value);
+            Assert.Equal(string.Empty, querySet.Filters.Single(f => f.Attribute == "key").Operation);
         }
 
         [Fact]

From ae452d28b70abdd243f45fd09ad6fc87473cc4c2 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 16 Dec 2017 07:31:24 -0600
Subject: [PATCH 058/227] fix(JsonApiDeSerializer): throw on possible null
 exception

---
 src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 25021c441e..1c0c5014f7 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -169,9 +169,12 @@ private object SetHasOneRelationship(object entity,
             if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
             {
                 var relationshipAttr = _jsonApiContext.RequestEntity.Relationships
-                        .SingleOrDefault(r => r.PublicRelationshipName == relationshipName);
+                    .SingleOrDefault(r => r.PublicRelationshipName == relationshipName);
 
-                var data = (Dictionary<string, string>)relationshipData.ExposedData;
+                if (relationshipAttr == null)
+                    throw new JsonApiException(400, $"{_jsonApiContext.RequestEntity.EntityName} does not contain a relationship '{relationshipName}'");
+
+                var data = (Dictionary<string, string>) relationshipData.ExposedData;
 
                 if (data == null) return entity;
 

From a54a211a5e64f4d969d58afa827bde52600e29a3 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 16 Dec 2017 07:35:48 -0600
Subject: [PATCH 059/227] test(queryParser): add test coverage and handle
 exception

---
 src/JsonApiDotNetCore/Services/QueryParser.cs |  53 ++++---
 test/UnitTests/Services/QueryParser_Tests.cs  | 130 +++++++++++++++++-
 2 files changed, 165 insertions(+), 18 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 47f9efa631..2a97723347 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -112,38 +112,47 @@ protected virtual(string operation, string value) ParseFilterOperation(string va
             return (prefix, value);
         }
 
-        protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value) {
+        protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value)
+        {
             // expected input = page[size]=10
             //                  page[number]=1
             pageQuery = pageQuery ?? new PageQuery();
 
-            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
+            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
 
             const string SIZE = "size";
             const string NUMBER = "number";
 
             if (propertyName == SIZE)
-                pageQuery.PageSize = Convert.ToInt32(value);
+                pageQuery.PageSize = int.TryParse(value, out var pageSize) ?
+                pageSize :
+                throw new JsonApiException(400, $"Invalid page size '{value}'");
+
             else if (propertyName == NUMBER)
-                pageQuery.PageOffset = Convert.ToInt32(value);
+                pageQuery.PageOffset = int.TryParse(value, out var pageOffset) ?
+                pageOffset :
+                throw new JsonApiException(400, $"Invalid page size '{value}'");
 
             return pageQuery;
         }
 
         // sort=id,name
         // sort=-id
-        protected virtual List<SortQuery> ParseSortParameters(string value) {
+        protected virtual List<SortQuery> ParseSortParameters(string value)
+        {
             var sortParameters = new List<SortQuery>();
 
             const char DESCENDING_SORT_OPERATOR = '-';
             var sortSegments = value.Split(COMMA);
 
-            foreach (var sortSegment in sortSegments) {
+            foreach (var sortSegment in sortSegments)
+            {
 
                 var propertyName = sortSegment;
                 var direction = SortDirection.Ascending;
 
-                if (sortSegment[0] == DESCENDING_SORT_OPERATOR) {
+                if (sortSegment[0] == DESCENDING_SORT_OPERATOR)
+                {
                     direction = SortDirection.Descending;
                     propertyName = propertyName.Substring(1);
                 }
@@ -166,37 +175,47 @@ protected virtual List<string> ParseIncludedRelationships(string value) {
                 .ToList();
         }
 
-        protected virtual List<string> ParseFieldsQuery(string key, string value) {
+        protected virtual List<string> ParseFieldsQuery(string key, string value)
+        {
             // expected: fields[TYPE]=prop1,prop2
-            var typeName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
+            var typeName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
 
             const string ID = "Id";
             var includedFields = new List<string> { ID };
 
-            if (typeName != _controllerContext.RequestEntity.EntityName)
+            // this will not support nested inclusions, it requires that the typeName is the current request type
+            if (string.Equals(typeName, _controllerContext.RequestEntity.EntityName, StringComparison.OrdinalIgnoreCase) == false)
                 return includedFields;
 
             var fields = value.Split(COMMA);
-            foreach (var field in fields) {
-                var internalAttrName = _controllerContext.RequestEntity
+            foreach (var field in fields)
+            {
+                var attr = _controllerContext.RequestEntity
                     .Attributes
-                    .SingleOrDefault(attr => attr.PublicAttributeName == field)
-                    .InternalAttributeName;
+                    .SingleOrDefault(a => string.Equals(a.PublicAttributeName, field, StringComparison.OrdinalIgnoreCase));
+
+                if (attr == null) throw new JsonApiException(400, $"'{_controllerContext.RequestEntity.EntityName}' does not contain '{field}'.");
+
+                var internalAttrName = attr.InternalAttributeName;
                 includedFields.Add(internalAttrName);
             }
 
             return includedFields;
         }
 
-        protected virtual AttrAttribute GetAttribute(string propertyName) {
-            try {
+        protected virtual AttrAttribute GetAttribute(string propertyName)
+        {
+            try
+            {
                 return _controllerContext
                     .RequestEntity
                     .Attributes
                     .Single(attr =>
                         string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
                     );
-            } catch (InvalidOperationException e) {
+            }
+            catch (InvalidOperationException e)
+            {
                 throw new JsonApiException(400, $"Attribute '{propertyName}' does not exist on resource '{_controllerContext.RequestEntity.EntityName}'", e);
             }
         }
diff --git a/test/UnitTests/Services/QueryParser_Tests.cs b/test/UnitTests/Services/QueryParser_Tests.cs
index abe5d75568..ed7808d1f4 100644
--- a/test/UnitTests/Services/QueryParser_Tests.cs
+++ b/test/UnitTests/Services/QueryParser_Tests.cs
@@ -224,5 +224,133 @@ public void Can_Disable_Fields()
             // assert
             Assert.Empty(querySet.Fields);
         }
+
+        [Fact]
+        public void Can_Parse_Fields_Query()
+        {
+            // arrange
+            const string type = "articles";
+            const string attrName = "some-field";
+            const string internalAttrName = "SomeField";
+
+            var query = new Dictionary<string, StringValues> { { $"fields[{type}]", new StringValues(attrName) } };
+
+            _queryCollectionMock
+                .Setup(m => m.GetEnumerator())
+                .Returns(query.GetEnumerator());
+
+            _controllerContextMock
+                .Setup(m => m.RequestEntity)
+                .Returns(new ContextEntity
+                {
+                    EntityName = type,
+                        Attributes = new List<AttrAttribute>
+                        {
+                            new AttrAttribute(attrName)
+                            {
+                                InternalAttributeName = internalAttrName
+                            }
+                        }
+                });
+
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            var querySet = queryParser.Parse(_queryCollectionMock.Object);
+
+            // assert
+            Assert.NotEmpty(querySet.Fields);
+            Assert.Equal(2, querySet.Fields.Count);
+            Assert.Equal("Id", querySet.Fields[0]);
+            Assert.Equal(internalAttrName, querySet.Fields[1]);
+        }
+
+        [Fact]
+        public void Throws_JsonApiException_If_Field_DoesNotExist()
+        {
+            // arrange
+            const string type = "articles";
+            const string attrName = "dne";
+
+            var query = new Dictionary<string, StringValues> { { $"fields[{type}]", new StringValues(attrName) } };
+
+            _queryCollectionMock
+                .Setup(m => m.GetEnumerator())
+                .Returns(query.GetEnumerator());
+
+            _controllerContextMock
+                .Setup(m => m.RequestEntity)
+                .Returns(new ContextEntity
+                {
+                    EntityName = type,
+                        Attributes = new List<AttrAttribute>()
+                });
+
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act , assert
+            var ex = Assert.Throws<JsonApiException>(() => queryParser.Parse(_queryCollectionMock.Object));
+            Assert.Equal(400, ex.GetStatusCode());
+        }
+
+        [Theory]
+        [InlineData("1", 1, false)]
+        [InlineData("abcde", 0, true)]
+        [InlineData("", 0, true)]
+        public void Can_Parse_Page_Size_Query(string value, int expectedValue, bool shouldThrow)
+        {
+            // arrange
+            var query = new Dictionary<string, StringValues>
+                { { "page[size]", new StringValues(value) }
+                };
+
+            _queryCollectionMock
+                .Setup(m => m.GetEnumerator())
+                .Returns(query.GetEnumerator());
+
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            if (shouldThrow)
+            {
+                var ex = Assert.Throws<JsonApiException>(() => queryParser.Parse(_queryCollectionMock.Object));
+                Assert.Equal(400, ex.GetStatusCode());
+            }
+            else
+            {
+                var querySet = queryParser.Parse(_queryCollectionMock.Object);
+                Assert.Equal(expectedValue, querySet.PageQuery.PageSize);
+            }
+        }
+
+        [Theory]
+        [InlineData("1", 1, false)]
+        [InlineData("abcde", 0, true)]
+        [InlineData("", 0, true)]
+        public void Can_Parse_Page_Number_Query(string value, int expectedValue, bool shouldThrow)
+        {
+            // arrange
+            var query = new Dictionary<string, StringValues>
+                { { "page[number]", new StringValues(value) }
+                };
+
+            _queryCollectionMock
+                .Setup(m => m.GetEnumerator())
+                .Returns(query.GetEnumerator());
+
+            var queryParser = new QueryParser(_controllerContextMock.Object, new JsonApiOptions());
+
+            // act
+            if (shouldThrow)
+            {
+                var ex = Assert.Throws<JsonApiException>(() => queryParser.Parse(_queryCollectionMock.Object));
+                Assert.Equal(400, ex.GetStatusCode());
+            }
+            else
+            {
+                var querySet = queryParser.Parse(_queryCollectionMock.Object);
+                Assert.Equal(expectedValue, querySet.PageQuery.PageOffset);
+            }
+        }
     }
-}
+}
\ No newline at end of file

From 2b1cbcc52b626c59cda82d788d6c96123ed6c693 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 16 Dec 2017 07:37:08 -0600
Subject: [PATCH 060/227] fix(ContextGraph): return null instead of throwing
 null exception

---
 src/JsonApiDotNetCore/Internal/ContextGraph.cs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/JsonApiDotNetCore/Internal/ContextGraph.cs b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
index fd29794194..163196341b 100644
--- a/src/JsonApiDotNetCore/Internal/ContextGraph.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
@@ -1,7 +1,7 @@
-using System.Reflection;
+using System;
 using System.Collections.Generic;
 using System.Linq;
-using System;
+using System.Reflection;
 
 namespace JsonApiDotNetCore.Internal
 {
@@ -34,9 +34,9 @@ public string GetRelationshipName<TParent>(string relationshipName)
         {
             var entityType = typeof(TParent);
             return Entities
-                .SingleOrDefault(e => e.EntityType == entityType)
-                .Relationships
-                .SingleOrDefault(r => string.Equals(r.PublicRelationshipName, relationshipName, StringComparison.OrdinalIgnoreCase))
+                .SingleOrDefault(e => e.EntityType == entityType) 
+                ?.Relationships
+                .SingleOrDefault(r => string.Equals(r.PublicRelationshipName, relationshipName, StringComparison.OrdinalIgnoreCase)) 
                 ?.InternalRelationshipName;
         }
     }

From 5eb948f3c46227393de82f71a87618891e8c686c Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 16 Dec 2017 07:38:28 -0600
Subject: [PATCH 061/227] fix(queryParser): add missing usings

---
 test/UnitTests/Services/QueryParser_Tests.cs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/test/UnitTests/Services/QueryParser_Tests.cs b/test/UnitTests/Services/QueryParser_Tests.cs
index ed7808d1f4..64c9830f2b 100644
--- a/test/UnitTests/Services/QueryParser_Tests.cs
+++ b/test/UnitTests/Services/QueryParser_Tests.cs
@@ -2,6 +2,8 @@
 using System.Linq;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Controllers;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Primitives;

From 6d52888ca7a3146d76c201beee208661b39e72a9 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 16 Dec 2017 07:49:48 -0600
Subject: [PATCH 062/227] fix(props): bump to netstandard2.0

fixing rebase
---
 build/dependencies.props | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/build/dependencies.props b/build/dependencies.props
index d4686bba2e..13b9ba4ecb 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -1,7 +1,7 @@
 <Project>
   <PropertyGroup>
-    <NetCoreAppVersion>netcoreapp1.1</NetCoreAppVersion>
-    <NetStandardVersion>netstandard1.6</NetStandardVersion>
+    <NetCoreAppVersion>netcoreapp2.0</NetCoreAppVersion>
+    <NetStandardVersion>netstandard2.0</NetStandardVersion>
   </PropertyGroup>
   <PropertyGroup>
     <MoqVersion>4.7.10</MoqVersion>

From f2ae1127e303d0f3a335b81706ce192384c2fde6 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 06:43:50 -0600
Subject: [PATCH 063/227] feat(AttrAttribute): add isSortable and isFilterable

---
 src/JsonApiDotNetCore/AssemblyInfo.cs             |  4 ++++
 .../Internal/Query/AttrFilterQuery.cs             | 14 ++++++++++----
 .../Internal/Query/RelatedAttrFilterQuery.cs      | 10 ++++++++--
 src/JsonApiDotNetCore/Models/AttrAttribute.cs     | 15 +++++++++------
 .../Models/RelationshipAttribute.cs               |  8 ++++----
 src/JsonApiDotNetCore/Services/QueryParser.cs     |  3 +++
 6 files changed, 38 insertions(+), 16 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/AssemblyInfo.cs

diff --git a/src/JsonApiDotNetCore/AssemblyInfo.cs b/src/JsonApiDotNetCore/AssemblyInfo.cs
new file mode 100644
index 0000000000..f03399b449
--- /dev/null
+++ b/src/JsonApiDotNetCore/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+using System.Runtime.CompilerServices;
+[assembly:InternalsVisibleTo("UnitTests")]
+[assembly:InternalsVisibleTo("JsonApiDotNetCoreExampleTests")]
+[assembly:InternalsVisibleTo("NoEntityFrameworkTests")]
diff --git a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
index 74db2b342e..e94f872b54 100644
--- a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
@@ -17,14 +17,20 @@ public AttrFilterQuery(
 
             var attribute = GetAttribute(filterQuery.Attribute);
 
-            FilteredAttribute = attribute ?? throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
+            if(attribute == null)
+                throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
+
+            if(attribute.IsFilterable == false)
+                throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'.");
+
+            FilteredAttribute = attribute;
             PropertyValue = filterQuery.Value;
             FilterOperation = GetFilterOperation(filterQuery.Operation);
         }
 
-        public AttrAttribute FilteredAttribute { get; set; }
-        public string PropertyValue { get; set; }
-        public FilterOperations FilterOperation { get; set; }
+        public AttrAttribute FilteredAttribute { get; }
+        public string PropertyValue { get; }
+        public FilterOperations FilterOperation { get; }
 
         private AttrAttribute GetAttribute(string attribute) =>  
             _jsonApiContext.RequestEntity.Attributes.FirstOrDefault(
diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
index 3b249c176c..52d7c66f41 100644
--- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
@@ -19,12 +19,18 @@ public RelatedAttrFilterQuery(
 
             var relationship = GetRelationship(relationshipArray[0]);
             if (relationship == null)
-                throw new JsonApiException(400, $"{relationshipArray[0]} is not a valid relationship.");
+                throw new JsonApiException(400, $"{relationshipArray[1]} is not a valid relationship on {relationshipArray[0]}.");
 
             var attribute = GetAttribute(relationship, relationshipArray[1]);
+            
+            if(attribute == null)
+                throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
+
+            if(attribute.IsFilterable == false)
+                throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'.");
 
             FilteredRelationship = relationship;
-            FilteredAttribute = attribute ?? throw new JsonApiException(400, $"{relationshipArray[1]} is not a valid attribute on {relationshipArray[0]}.");
+            FilteredAttribute = attribute;
             PropertyValue = filterQuery.Value;
             FilterOperation = GetFilterOperation(filterQuery.Operation);
         }
diff --git a/src/JsonApiDotNetCore/Models/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
index f84fd229ef..9fa869aeb0 100644
--- a/src/JsonApiDotNetCore/Models/AttrAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
@@ -1,27 +1,30 @@
 using System;
-using System.Reflection;
 using JsonApiDotNetCore.Internal;
 
 namespace JsonApiDotNetCore.Models
 {
     public class AttrAttribute : Attribute
     {
-        public AttrAttribute(string publicName, bool isImmutable = false)
+        public AttrAttribute(string publicName, bool isImmutable = false, bool isFilterable = true, bool isSortable = true)
         {
             PublicAttributeName = publicName;
             IsImmutable = isImmutable;
+            IsFilterable = isFilterable;
+            IsSortable = isSortable;
         }
 
-        public AttrAttribute(string publicName, string internalName, bool isImmutable = false)
+        internal AttrAttribute(string publicName, string internalName, bool isImmutable = false)
         {
             PublicAttributeName = publicName;
             InternalAttributeName = internalName;
             IsImmutable = isImmutable;
         }
 
-        public string PublicAttributeName { get; set; }
-        public string InternalAttributeName { get; set; }
-        public bool IsImmutable { get; set; }
+        public string PublicAttributeName { get; }
+        public string InternalAttributeName { get; }
+        public bool IsImmutable { get; }
+        public bool IsFilterable { get; }
+        public bool IsSortable { get; }
 
         public object GetValue(object entity)
         {
diff --git a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
index 93662032a5..4f6d42f47e 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
@@ -10,12 +10,12 @@ protected RelationshipAttribute(string publicName, Link documentLinks)
             DocumentLinks = documentLinks;
         }
 
-        public string PublicRelationshipName { get; set; }
-        public string InternalRelationshipName { get; set; }
-        public Type Type { get; set; }
+        public string PublicRelationshipName { get; }
+        public string InternalRelationshipName { get; }
+        public Type Type { get; }
         public bool IsHasMany => GetType() == typeof(HasManyAttribute);
         public bool IsHasOne => GetType() == typeof(HasOneAttribute);
-        public Link DocumentLinks { get; set; } = Link.All;
+        public Link DocumentLinks { get; } = Link.All;
 
         public abstract void SetValue(object entity, object newValue);
 
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 2a97723347..d9dfab532d 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -159,6 +159,9 @@ protected virtual List<SortQuery> ParseSortParameters(string value)
 
                 var attribute = GetAttribute(propertyName);
 
+                if(attribute.IsSortable == false)
+                    throw new JsonApiException(400, $"Sort is not allowed for attribute '{attribute.PublicAttributeName}'.");
+
                 sortParameters.Add(new SortQuery(direction, attribute));
             };
 

From 6cdd04bb53dbae932ab66503e430a971fc92c9be Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 19:57:34 -0600
Subject: [PATCH 064/227] fix(Attr/RelationshipAttibute): make setters internal

---
 benchmarks/Query/QueryParser_Benchmarks.cs            | 4 +---
 src/JsonApiDotNetCore/AssemblyInfo.cs                 | 1 +
 src/JsonApiDotNetCore/Models/AttrAttribute.cs         | 2 +-
 src/JsonApiDotNetCore/Models/HasManyAttribute.cs      | 6 +-----
 src/JsonApiDotNetCore/Models/HasOneAttribute.cs       | 6 +-----
 src/JsonApiDotNetCore/Models/RelationshipAttribute.cs | 4 ++--
 6 files changed, 7 insertions(+), 16 deletions(-)

diff --git a/benchmarks/Query/QueryParser_Benchmarks.cs b/benchmarks/Query/QueryParser_Benchmarks.cs
index 61fe3b1bc2..de82baa60f 100644
--- a/benchmarks/Query/QueryParser_Benchmarks.cs
+++ b/benchmarks/Query/QueryParser_Benchmarks.cs
@@ -24,9 +24,7 @@ public QueryParser_Benchmarks() {
             var controllerContextMock = new Mock<IControllerContext>();
             controllerContextMock.Setup(m => m.RequestEntity).Returns(new ContextEntity {
                 Attributes = new List<AttrAttribute> {
-                    new AttrAttribute(ATTRIBUTE) {
-                        InternalAttributeName = ATTRIBUTE
-                    }
+                    new AttrAttribute(ATTRIBUTE, ATTRIBUTE)
                 }
             });
             var options = new JsonApiOptions();
diff --git a/src/JsonApiDotNetCore/AssemblyInfo.cs b/src/JsonApiDotNetCore/AssemblyInfo.cs
index f03399b449..f11bb5d594 100644
--- a/src/JsonApiDotNetCore/AssemblyInfo.cs
+++ b/src/JsonApiDotNetCore/AssemblyInfo.cs
@@ -2,3 +2,4 @@
 [assembly:InternalsVisibleTo("UnitTests")]
 [assembly:InternalsVisibleTo("JsonApiDotNetCoreExampleTests")]
 [assembly:InternalsVisibleTo("NoEntityFrameworkTests")]
+[assembly:InternalsVisibleTo("Benchmarks")]
diff --git a/src/JsonApiDotNetCore/Models/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
index 9fa869aeb0..5be036636d 100644
--- a/src/JsonApiDotNetCore/Models/AttrAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
@@ -21,7 +21,7 @@ internal AttrAttribute(string publicName, string internalName, bool isImmutable
         }
 
         public string PublicAttributeName { get; }
-        public string InternalAttributeName { get; }
+        public string InternalAttributeName { get; internal set; }
         public bool IsImmutable { get; }
         public bool IsFilterable { get; }
         public bool IsSortable { get; }
diff --git a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
index 379458014b..b4fd1b42ec 100644
--- a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
@@ -1,14 +1,10 @@
-using System.Reflection;
-
 namespace JsonApiDotNetCore.Models
 {
     public class HasManyAttribute : RelationshipAttribute
     {
         public HasManyAttribute(string publicName, Link documentLinks = Link.All)
         : base(publicName, documentLinks)
-        {
-            PublicRelationshipName = publicName;
-        }
+        { }
 
         public override void SetValue(object entity, object newValue)
         {
diff --git a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
index 296b71369e..0dd20e73e7 100644
--- a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
@@ -1,14 +1,10 @@
-using System.Reflection;
-
 namespace JsonApiDotNetCore.Models
 {
     public class HasOneAttribute : RelationshipAttribute
     {
         public HasOneAttribute(string publicName, Link documentLinks = Link.All)
         : base(publicName, documentLinks)
-        {
-            PublicRelationshipName = publicName;
-        }
+        { }
 
         public override void SetValue(object entity, object newValue)
         {
diff --git a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
index 4f6d42f47e..852b602bea 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
@@ -11,8 +11,8 @@ protected RelationshipAttribute(string publicName, Link documentLinks)
         }
 
         public string PublicRelationshipName { get; }
-        public string InternalRelationshipName { get; }
-        public Type Type { get; }
+        public string InternalRelationshipName { get; internal set; }
+        public Type Type { get; internal set; }
         public bool IsHasMany => GetType() == typeof(HasManyAttribute);
         public bool IsHasOne => GetType() == typeof(HasOneAttribute);
         public Link DocumentLinks { get; } = Link.All;

From cb0780f48f64a4bd5802ee44ebaa9f19f7008a55 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 3 Jan 2018 06:00:41 -0600
Subject: [PATCH 065/227] test(acceptance): verify filter/sort limitations

---
 .../Models/TodoItem.cs                        |  2 +-
 .../Acceptance/Spec/AttributeFilterTests.cs   | 37 +++++++++++--------
 .../Acceptance/Spec/AttributeSortTests.cs     | 34 +++++++++++++++++
 3 files changed, 56 insertions(+), 17 deletions(-)
 create mode 100644 test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs

diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs
index 7257835791..fecd16319d 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs
@@ -22,7 +22,7 @@ public TodoItem()
         [Attr("created-date")]
         public DateTime CreatedDate { get; set; }
 
-        [Attr("achieved-date")]
+        [Attr("achieved-date", isFilterable: false, isSortable: false)]
         public DateTime? AchievedDate { get; set; }
         
         public int? OwnerId { get; set; }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index 740a61193c..dd7c673b4c 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -1,4 +1,5 @@
-using System.Linq;
+using System;
+using System.Linq;
 using System.Net;
 using System.Net.Http;
 using System.Threading.Tasks;
@@ -8,8 +9,6 @@
 using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.TestHost;
 using Newtonsoft.Json;
 using Xunit;
 using Person = JsonApiDotNetCoreExample.Models.Person;
@@ -44,17 +43,13 @@ public async Task Can_Filter_On_Guid_Properties()
             var todoItem = _todoItemFaker.Generate();
             context.TodoItems.Add(todoItem);
             await context.SaveChangesAsync();
-            
-            var builder = new WebHostBuilder()
-                .UseStartup<Startup>();
+
             var httpMethod = new HttpMethod("GET");
             var route = $"/api/v1/todo-items?filter[guid-property]={todoItem.GuidProperty}";
-            var server = new TestServer(builder);
-            var client = server.CreateClient();
             var request = new HttpRequestMessage(httpMethod, route);
 
             // act
-            var response = await client.SendAsync(request);
+            var response = await _fixture.Client.SendAsync(request);
             var body = await response.Content.ReadAsStringAsync();
             var deserializedBody = _fixture
                 .GetService<IJsonApiDeSerializer>()
@@ -68,7 +63,6 @@ public async Task Can_Filter_On_Guid_Properties()
             Assert.Equal(todoItem.GuidProperty, todoItemResponse.GuidProperty);
         }
 
-
         [Fact]
         public async Task Can_Filter_On_Related_Attrs()
         {
@@ -79,17 +73,13 @@ public async Task Can_Filter_On_Related_Attrs()
             todoItem.Owner = person;
             context.TodoItems.Add(todoItem);
             await context.SaveChangesAsync();
-            
-            var builder = new WebHostBuilder()
-                .UseStartup<Startup>();
+
             var httpMethod = new HttpMethod("GET");
             var route = $"/api/v1/todo-items?include=owner&filter[owner.first-name]={person.FirstName}";
-            var server = new TestServer(builder);
-            var client = server.CreateClient();
             var request = new HttpRequestMessage(httpMethod, route);
 
             // act
-            var response = await client.SendAsync(request);
+            var response = await _fixture.Client.SendAsync(request);
             var body = await response.Content.ReadAsStringAsync();
             var documents = JsonConvert.DeserializeObject<Documents>(await response.Content.ReadAsStringAsync());
             var included = documents.Included;
@@ -101,5 +91,20 @@ public async Task Can_Filter_On_Related_Attrs()
             foreach(var item in included)
                 Assert.Equal(person.FirstName, item.Attributes["first-name"]);
         }
+
+        [Fact]
+        public async Task Cannot_Filter_If_Explicitly_Forbidden()
+        {
+            // arrange
+            var httpMethod = new HttpMethod("GET");
+            var route = $"/api/v1/todo-items?include=owner&filter[achieved-date]={DateTime.UtcNow.Date}";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // act
+            var response = await _fixture.Client.SendAsync(request);
+
+            // assert
+            Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+        }
     }
 }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs
new file mode 100644
index 0000000000..8525f251d1
--- /dev/null
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs
@@ -0,0 +1,34 @@
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using JsonApiDotNetCoreExample;
+using Xunit;
+
+namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
+{
+    [Collection("WebHostCollection")]
+    public class AttributeSortTests
+    {
+        private TestFixture<Startup> _fixture;
+
+        public AttributeSortTests(TestFixture<Startup> fixture)
+        {
+            _fixture = fixture;
+        }
+
+        [Fact]
+        public async Task Cannot_Sort_If_Explicitly_Forbidden()
+        {
+            // arrange
+            var httpMethod = new HttpMethod("GET");
+            var route = $"/api/v1/todo-items?include=owner&sort=achieved-date";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // act
+            var response = await _fixture.Client.SendAsync(request);
+
+            // assert
+            Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+        }
+    }
+}

From ebcb575fdfe87fea1949de5cb14dd433436cabc0 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 06:17:57 -0600
Subject: [PATCH 066/227] chore(csproj): upgrade xunit and include dotnet watch

---
 build/dependencies.props                                    | 2 +-
 .../JsonApiDotNetCoreExampleTests.csproj                    | 6 +++++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/build/dependencies.props b/build/dependencies.props
index 13b9ba4ecb..0ef1b750a7 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -5,7 +5,7 @@
   </PropertyGroup>
   <PropertyGroup>
     <MoqVersion>4.7.10</MoqVersion>
-    <xUnitVersion>2.2.0</xUnitVersion>
+    <xUnitVersion>2.3.1</xUnitVersion>
     <BogusVersion>8.0.1-beta-1</BogusVersion>
   </PropertyGroup>
 </Project>
diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
index 1b40e2dd73..43500cb84b 100755
--- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
@@ -30,5 +30,9 @@
     <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
     <PackageReference Include="Moq" Version="$(MoqVersion)" />
   </ItemGroup>
-
+  
+  <ItemGroup>
+    <DotNetCliToolReference Include="dotnet-xunit" Version="$(XUnitVersion)" />
+    <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="1.0.0" />
+  </ItemGroup>
 </Project>

From 9f1beab49c5c83e41df3a2f53615aeeca063e907 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 06:18:49 -0600
Subject: [PATCH 067/227] feat(DbContextReolver): make the implementation
 generic and remove injection of DbContext

---
 .../Data/DbContextResolver.cs                 |  8 ++++----
 .../IServiceCollectionExtensions.cs           |  4 ++--
 .../Internal/Generics/GenericProcessor.cs     |  5 +++--
 .../Generics/GenericProcessorFactory.cs       |  6 ++++--
 .../IServiceCollectionExtensionsTests.cs      | 20 +++++++++----------
 5 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DbContextResolver.cs b/src/JsonApiDotNetCore/Data/DbContextResolver.cs
index 8aedee0f4e..7cfe0a4278 100644
--- a/src/JsonApiDotNetCore/Data/DbContextResolver.cs
+++ b/src/JsonApiDotNetCore/Data/DbContextResolver.cs
@@ -1,14 +1,14 @@
-using System;
 using JsonApiDotNetCore.Extensions;
 using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Data
 {
-    public class DbContextResolver : IDbContextResolver
+    public class DbContextResolver<TContext>  : IDbContextResolver
+        where TContext : DbContext
     {
-        private readonly DbContext _context;
+        private readonly TContext _context;
 
-        public DbContextResolver(DbContext context)
+        public DbContextResolver(TContext context)
         {
             _context = context;
         }
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index afcc11ee8d..1549e77e0f 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -77,7 +77,8 @@ public static void AddJsonApiInternals<TContext>(
             if (jsonApiOptions.ContextGraph == null)
                 jsonApiOptions.BuildContextGraph<TContext>(null);
 
-            services.AddScoped(typeof(DbContext), typeof(TContext));
+            services.AddScoped<IDbContextResolver, DbContextResolver<TContext>>();
+
             AddJsonApiInternals(services, jsonApiOptions);
         }
 
@@ -91,7 +92,6 @@ public static void AddJsonApiInternals(
                 services.AddSingleton<DbContextOptions>(new DbContextOptionsBuilder().Options);
             }
 
-            services.AddScoped<IDbContextResolver, DbContextResolver>();
             services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
             services.AddScoped(typeof(IEntityRepository<,>), typeof(DefaultEntityRepository<,>));
             services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
index ce76b47dae..781f8ae7f3 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
@@ -1,6 +1,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
@@ -10,9 +11,9 @@ namespace JsonApiDotNetCore.Internal.Generics
     public class GenericProcessor<T> : IGenericProcessor where T : class, IIdentifiable
     {
         private readonly DbContext _context;
-        public GenericProcessor(DbContext context)
+        public GenericProcessor(IDbContextResolver contextResolver)
         {
-            _context = context;
+            _context = contextResolver.GetContext();
         }
 
         public async Task UpdateRelationshipsAsync(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds)
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
index a238e4ef9f..6918976590 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
@@ -1,4 +1,5 @@
 using System;
+using JsonApiDotNetCore.Data;
 using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Internal.Generics
@@ -8,10 +9,11 @@ public class GenericProcessorFactory : IGenericProcessorFactory
         private readonly DbContext _dbContext;
         private readonly IServiceProvider _serviceProvider;
 
-        public GenericProcessorFactory(DbContext dbContext, 
+        public GenericProcessorFactory(
+            IDbContextResolver dbContextResolver, 
             IServiceProvider serviceProvider)
         {
-            _dbContext = dbContext;
+            _dbContext = dbContextResolver.GetContext();
             _serviceProvider = serviceProvider;
         }
 
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs b/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
index 95b05df096..5d68306493 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
@@ -1,19 +1,19 @@
-using Xunit;
 using JsonApiDotNetCore.Builders;
-using Microsoft.Extensions.DependencyInjection;
-using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Configuration;
-using Microsoft.EntityFrameworkCore;
 using JsonApiDotNetCore.Data;
+using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Formatters;
 using JsonApiDotNetCore.Internal;
-using Microsoft.AspNetCore.Http;
+using JsonApiDotNetCore.Internal.Generics;
+using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
 using JsonApiDotNetCoreExample.Data;
-using Microsoft.Extensions.Caching.Memory;
 using JsonApiDotNetCoreExample.Models;
-using JsonApiDotNetCore.Serialization;
-using JsonApiDotNetCore.Formatters;
-using JsonApiDotNetCore.Internal.Generics;
+using Microsoft.AspNetCore.Http;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.DependencyInjection;
+using Xunit;
 
 namespace JsonApiDotNetCoreExampleTests.Unit.Extensions
 {
@@ -36,7 +36,7 @@ public void AddJsonApiInternals_Adds_All_Required_Services()
             var provider = services.BuildServiceProvider();
 
             // assert
-            Assert.NotNull(provider.GetService<DbContext>());
+            Assert.NotNull(provider.GetService<IDbContextResolver>());
             Assert.NotNull(provider.GetService(typeof(IEntityRepository<TodoItem>)));
             Assert.NotNull(provider.GetService<JsonApiOptions>());
             Assert.NotNull(provider.GetService<IContextGraph>());

From 6404ba18892716f802a4bc47a6d62a05d6b6e30c Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 12:51:51 -0600
Subject: [PATCH 068/227] feat(*): remove non-EF dependencies on
 DbContextResolver

---
 src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs    | 9 +++++----
 .../Internal/Generics/GenericProcessorFactory.cs         | 8 +-------
 src/JsonApiDotNetCore/Services/IJsonApiContext.cs        | 3 ---
 src/JsonApiDotNetCore/Services/JsonApiContext.cs         | 6 ------
 .../Repositories/AuthorizedTodoItemsRepository.cs        | 3 ++-
 5 files changed, 8 insertions(+), 21 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index 1199389c60..7e7f4345f4 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -20,8 +20,9 @@ public class DefaultEntityRepository<TEntity>
     {
         public DefaultEntityRepository(
             ILoggerFactory loggerFactory,
-            IJsonApiContext jsonApiContext)
-        : base(loggerFactory, jsonApiContext)
+            IJsonApiContext jsonApiContext,
+            IDbContextResolver contextResolver)
+        : base(loggerFactory, jsonApiContext, contextResolver)
         { }
     }
 
@@ -50,9 +51,9 @@ public DefaultEntityRepository(
 
         public DefaultEntityRepository(
             ILoggerFactory loggerFactory,
-            IJsonApiContext jsonApiContext)
+            IJsonApiContext jsonApiContext,
+            IDbContextResolver contextResolver)
         {
-            var contextResolver = jsonApiContext.GetDbContextResolver();
             _context = contextResolver.GetContext();
             _dbSet = contextResolver.GetDbSet<TEntity>();
             _jsonApiContext = jsonApiContext;
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
index 6918976590..4b4e76525c 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
@@ -1,19 +1,13 @@
 using System;
-using JsonApiDotNetCore.Data;
-using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Internal.Generics
 {
     public class GenericProcessorFactory : IGenericProcessorFactory
     {
-        private readonly DbContext _dbContext;
         private readonly IServiceProvider _serviceProvider;
 
-        public GenericProcessorFactory(
-            IDbContextResolver dbContextResolver, 
-            IServiceProvider serviceProvider)
+        public GenericProcessorFactory(IServiceProvider serviceProvider)
         {
-            _dbContext = dbContextResolver.GetContext();
             _serviceProvider = serviceProvider;
         }
 
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index 7b1b9e67a8..ee7ee10a35 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -1,9 +1,7 @@
 using System;
 using System.Collections.Generic;
-using System.Reflection;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
@@ -29,6 +27,5 @@ public interface IJsonApiContext
         Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
         Type ControllerType { get; set; }
         TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
-        IDbContextResolver GetDbContextResolver();
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index b223e47bf5..5304d77b29 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -3,7 +3,6 @@
 using System.Linq;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
@@ -15,12 +14,10 @@ namespace JsonApiDotNetCore.Services
     public class JsonApiContext : IJsonApiContext
     {
         private readonly IHttpContextAccessor _httpContextAccessor;
-        private readonly IDbContextResolver _contextResolver;
         private readonly IQueryParser _queryParser;
         private readonly IControllerContext _controllerContext;
 
         public JsonApiContext(
-            IDbContextResolver contextResolver,
             IContextGraph contextGraph,
             IHttpContextAccessor httpContextAccessor,
             JsonApiOptions options,
@@ -29,7 +26,6 @@ public JsonApiContext(
             IQueryParser queryParser,
             IControllerContext controllerContext)
         {
-            _contextResolver = contextResolver;
             ContextGraph = contextGraph;
             _httpContextAccessor = httpContextAccessor;
             Options = options;
@@ -81,8 +77,6 @@ public IJsonApiContext ApplyContext<T>(object controller)
             return this;
         }
 
-        public IDbContextResolver GetDbContextResolver() => _contextResolver;
-
         private PageManager GetPageManager()
         {
             if (Options.DefaultPageSize == 0 && (QuerySet == null || QuerySet.PageQuery.PageSize == 0))
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
index 7e9abf3784..32cb24cdcf 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
@@ -16,8 +16,9 @@ public class AuthorizedTodoItemsRepository : DefaultEntityRepository<TodoItem>
         public AuthorizedTodoItemsRepository(
             ILoggerFactory loggerFactory,
             IJsonApiContext jsonApiContext,
+            IDbContextResolver contextResolver,
             IAuthorizationService authService)
-        : base(loggerFactory, jsonApiContext)
+        : base(loggerFactory, jsonApiContext, contextResolver)
         {
             _logger = loggerFactory.CreateLogger<AuthorizedTodoItemsRepository>();
             _authService = authService;

From 0045fcd41006fa8380c1e3d9fbabbc2c02ca7755 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 12:52:15 -0600
Subject: [PATCH 069/227] ci(Build.ps1): check exit codes

---
 Build.ps1 | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/Build.ps1 b/Build.ps1
index 8b4e2cf44c..e51473adf2 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -9,34 +9,52 @@ function Get-Version-Suffix-From-Tag
   return $final
 }
 
+function CheckLastExitCode {
+    param ([int[]]$SuccessCodes = @(0), [scriptblock]$CleanupScript=$null)
+
+    if ($SuccessCodes -notcontains $LastExitCode) {
+        $msg = "EXE RETURNED EXIT CODE $LastExitCode"
+        throw $msg
+    }
+}
+
 $revision = @{ $true = $env:APPVEYOR_BUILD_NUMBER; $false = 1 }[$env:APPVEYOR_BUILD_NUMBER -ne $NULL];
 $revision = "{0:D4}" -f [convert]::ToInt32($revision, 10)
 
 dotnet restore
 
 dotnet test ./test/UnitTests/UnitTests.csproj
+CheckLastExitCode
+
 dotnet test ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+CheckLastExitCode
+
 dotnet test ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
+CheckLastExitCode
 
 dotnet build .\src\JsonApiDotNetCore -c Release
+CheckLastExitCode
 
-echo "APPVEYOR_REPO_TAG: $env:APPVEYOR_REPO_TAG"
+Write-Output "APPVEYOR_REPO_TAG: $env:APPVEYOR_REPO_TAG"
 
 If($env:APPVEYOR_REPO_TAG -eq $true) {
     $revision = Get-Version-Suffix-From-Tag
-    echo "VERSION-SUFFIX: $revision"
+    Write-Output "VERSION-SUFFIX: $revision"
 
     IF ([string]::IsNullOrWhitespace($revision)){
-        echo "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts"
+        Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts"
         dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts
+        CheckLastExitCode
     }
     Else {
-        echo "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision"
+        Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision"
         dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision 
+        CheckLastExitCode
     }
 }
 Else { 
-    echo "VERSION-SUFFIX: alpha1-$revision"
-    echo "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision"
+    Write-Output "VERSION-SUFFIX: alpha1-$revision"
+    Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision"
     dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision 
+    CheckLastExitCode
 }
\ No newline at end of file

From 318582ee558719d72c94844bd4c8bf9a8944e7f7 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 12:54:36 -0600
Subject: [PATCH 070/227] tests(DefaultEntityRepository): fix test setup

---
 test/UnitTests/Data/DefaultEntityRepository_Tests.cs | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/test/UnitTests/Data/DefaultEntityRepository_Tests.cs b/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
index e596b35317..50d24409f8 100644
--- a/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
+++ b/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
@@ -89,13 +89,10 @@ private DefaultEntityRepository<TodoItem> GetRepository()
                 .Setup(m => m.RelationshipsToUpdate)
                 .Returns(_relationshipsToUpdate);
 
-            _jsonApiContextMock
-                .Setup(m => m.GetDbContextResolver())
-                .Returns(_contextResolverMock.Object);
-
             return new DefaultEntityRepository<TodoItem>(
                 _loggFactoryMock.Object,
-                _jsonApiContextMock.Object);
+                _jsonApiContextMock.Object,
+                _contextResolverMock.Object);
         }
     }
 }

From 2cb6addce31720f0df8f7e343507128820ac77b6 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 13:13:42 -0600
Subject: [PATCH 071/227] chore(DefaultEntityRepository): drop obsolete
 constructor

---
 .../Data/DefaultEntityRepository.cs                 | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index 7e7f4345f4..5b5b0d1a55 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -36,19 +36,6 @@ public class DefaultEntityRepository<TEntity, TId>
         private readonly IJsonApiContext _jsonApiContext;
         private readonly IGenericProcessorFactory _genericProcessorFactory;
 
-        [Obsolete("DbContext is no longer directly injected into the ctor. Use JsonApiContext.GetDbContextResolver() instead")]
-        public DefaultEntityRepository(
-            DbContext context,
-            ILoggerFactory loggerFactory,
-            IJsonApiContext jsonApiContext)
-        {
-            _context = context;
-            _dbSet = context.GetDbSet<TEntity>();
-            _jsonApiContext = jsonApiContext;
-            _logger = loggerFactory.CreateLogger<DefaultEntityRepository<TEntity, TId>>();
-            _genericProcessorFactory = _jsonApiContext.GenericProcessorFactory;
-        }
-
         public DefaultEntityRepository(
             ILoggerFactory loggerFactory,
             IJsonApiContext jsonApiContext,

From 77933c8585421e85ea63122da870bcafdc79bf86 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 05:49:24 -0600
Subject: [PATCH 072/227] chore(ContextGraph): remove publicly accessible
 member

exposes unnecessary implementation details
---
 .../Builders/ContextGraphBuilder.cs           | 13 +++++-------
 .../Internal/ContextGraph.cs                  | 20 +++++++++++++------
 .../Internal/IContextGraph.cs                 |  2 +-
 3 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index e47dec2065..8b35584d0a 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -1,11 +1,11 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Reflection;
-using Microsoft.EntityFrameworkCore;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
-using JsonApiDotNetCore.Extensions;
-using System.Linq;
+using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Builders
 {
@@ -20,11 +20,8 @@ public IContextGraph Build()
             // this must be done at build so that call order doesn't matter
             _entities.ForEach(e => e.Links = GetLinkFlags(e.EntityType));
 
-            var graph = new ContextGraph()
-            {
-                Entities = _entities,
-                UsesDbContext = _usesDbContext
-            };
+            var graph = new ContextGraph(_entities, _usesDbContext);
+
             return graph;
         }
 
diff --git a/src/JsonApiDotNetCore/Internal/ContextGraph.cs b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
index 163196341b..bc3f037bf2 100644
--- a/src/JsonApiDotNetCore/Internal/ContextGraph.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
@@ -1,20 +1,28 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Reflection;
 
 namespace JsonApiDotNetCore.Internal
 {
     public class ContextGraph : IContextGraph
     {
-        public List<ContextEntity> Entities { get; set; }
-        public bool UsesDbContext { get; set; }
+        private List<ContextEntity> _entities;
+
+        public ContextGraph() { }
+        
+        public ContextGraph(List<ContextEntity> entities, bool usesDbContext) 
+        {
+            _entities = entities;
+            UsesDbContext = usesDbContext;
+        }
+
+        public bool UsesDbContext { get; }
 
         public ContextEntity GetContextEntity(string entityName)
-            => Entities.SingleOrDefault(e => string.Equals(e.EntityName, entityName, StringComparison.OrdinalIgnoreCase));
+            => _entities.SingleOrDefault(e => string.Equals(e.EntityName, entityName, StringComparison.OrdinalIgnoreCase));
 
         public ContextEntity GetContextEntity(Type entityType)
-            => Entities.SingleOrDefault(e => e.EntityType == entityType);
+            => _entities.SingleOrDefault(e => e.EntityType == entityType);
 
         public object GetRelationship<TParent>(TParent entity, string relationshipName)
         {
@@ -33,7 +41,7 @@ public object GetRelationship<TParent>(TParent entity, string relationshipName)
         public string GetRelationshipName<TParent>(string relationshipName)
         {
             var entityType = typeof(TParent);
-            return Entities
+            return _entities
                 .SingleOrDefault(e => e.EntityType == entityType) 
                 ?.Relationships
                 .SingleOrDefault(r => string.Equals(r.PublicRelationshipName, relationshipName, StringComparison.OrdinalIgnoreCase)) 
diff --git a/src/JsonApiDotNetCore/Internal/IContextGraph.cs b/src/JsonApiDotNetCore/Internal/IContextGraph.cs
index 707d6fd32d..5aa05bdacd 100644
--- a/src/JsonApiDotNetCore/Internal/IContextGraph.cs
+++ b/src/JsonApiDotNetCore/Internal/IContextGraph.cs
@@ -8,6 +8,6 @@ public interface IContextGraph
         string GetRelationshipName<TParent>(string relationshipName);
         ContextEntity GetContextEntity(string dbSetName);
         ContextEntity GetContextEntity(Type entityType);
-        bool UsesDbContext { get; set; }
+        bool UsesDbContext { get; }
     }
 }

From 16719acce01ec91a1dbb26e4485820620cce2ed3 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 05:49:55 -0600
Subject: [PATCH 073/227] chore(EntityResourceService): remove unused var
 declaration

---
 src/JsonApiDotNetCore/Services/EntityResourceService.cs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index 7db499fd5e..3fc143e1f3 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -166,8 +166,6 @@ private async Task<IEnumerable<T>> ApplyPageQueryAsync(IQueryable<T> entities)
             if (!pageManager.IsPaginated)
                 return entities;
 
-            var query = _jsonApiContext.QuerySet?.PageQuery ?? new PageQuery();
-
             _logger?.LogInformation($"Applying paging query. Fetching page {pageManager.CurrentPage} with {pageManager.PageSize} entities");
 
             return await _entities.PageAsync(entities, pageManager.PageSize, pageManager.CurrentPage);

From 8b59408ac2be04c2ef91c9730d4cd042b680c900 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 05:50:34 -0600
Subject: [PATCH 074/227] chore(example csproj): remove unnecessary members

---
 .../JsonApiDotNetCoreExampleTests.csproj                   | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
index 43500cb84b..da92260546 100755
--- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
@@ -2,12 +2,7 @@
   <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
-    <PreserveCompilationContext>true</PreserveCompilationContext>
-    <AssemblyName>JsonApiDotNetCoreExampleTests</AssemblyName>
-    <OutputType>Exe</OutputType>
-    <PackageId>JsonApiDotNetCoreExampleTests</PackageId>
-    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
-    <ServerGarbageCollection>true</ServerGarbageCollection>
+    <IsPackable>false</IsPackable>
   </PropertyGroup>
 
   <ItemGroup>

From d706d376734d6ca7d1b4ccf3dda98c7bbdc2fb7d Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 19 Dec 2017 05:52:28 -0600
Subject: [PATCH 075/227] chore(IQueryableExtensions): fix bad comments

---
 src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index c40d61b517..ee6b4451c5 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -163,11 +163,10 @@ private static Expression GetFilterExpressionLambda(Expression left, Expression
                     body = Expression.LessThanOrEqual(left, right);
                     break;
                 case FilterOperations.ge:
-                    // {model.Id <= 1}
+                    // {model.Id >= 1}
                     body = Expression.GreaterThanOrEqual(left, right);
                     break;
                 case FilterOperations.like:
-                    // {model.Id <= 1}
                     body = Expression.Call(left, "Contains", null, right);
                     break;
                 default:

From 604f4870b9b404d9747ce91166d4c1d4475bedcd Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 3 Jan 2018 06:35:28 -0600
Subject: [PATCH 076/227] chore(EntityResourceService): consolidate
 ShouldIncludeRelationships check

---
 src/JsonApiDotNetCore/Services/EntityResourceService.cs | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index 3fc143e1f3..cc1ba897e1 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -4,7 +4,6 @@
 using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.Logging;
@@ -47,7 +46,7 @@ public virtual async Task<IEnumerable<T>> GetAsync()
 
             entities = ApplySortAndFilterQuery(entities);
 
-            if (_jsonApiContext.QuerySet?.IncludedRelationships != null && _jsonApiContext.QuerySet.IncludedRelationships.Count > 0)
+            if (ShouldIncludeRelationships())
                 entities = IncludeRelationships(entities, _jsonApiContext.QuerySet.IncludedRelationships);
 
             if (_jsonApiContext.Options.IncludeTotalRecordCount)
@@ -61,13 +60,16 @@ public virtual async Task<IEnumerable<T>> GetAsync()
         public virtual async Task<T> GetAsync(TId id)
         {
             T entity;
-            if (_jsonApiContext.QuerySet?.IncludedRelationships != null)
+            if (ShouldIncludeRelationships())
                 entity = await GetWithRelationshipsAsync(id);
             else
                 entity = await _entities.GetAsync(id);
             return entity;
         }
 
+        private bool ShouldIncludeRelationships()
+            => (_jsonApiContext.QuerySet?.IncludedRelationships != null && _jsonApiContext.QuerySet.IncludedRelationships.Count > 0);
+
         private async Task<T> GetWithRelationshipsAsync(TId id)
         {
             var query = _entities.Get();

From 5f6b9bcad28120a79271adf7534971a1d1ad4e9d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20H=C3=BCbner?= <sven.huebner@zeiss.com>
Date: Tue, 2 Jan 2018 10:46:49 +0100
Subject: [PATCH 077/227] moved Sort into an IQueryable extension method

---
 .../Data/DefaultEntityRepository.cs             | 12 +-----------
 .../Extensions/IQueryableExtensions.cs          | 17 ++++++++++++++++-
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index 5b5b0d1a55..b31f4abaed 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -69,17 +69,7 @@ public virtual IQueryable<TEntity> Filter(IQueryable<TEntity> entities, FilterQu
 
         public virtual IQueryable<TEntity> Sort(IQueryable<TEntity> entities, List<SortQuery> sortQueries)
         {
-            if (sortQueries == null || sortQueries.Count == 0)
-                return entities;
-
-            var orderedEntities = entities.Sort(sortQueries[0]);
-
-            if (sortQueries.Count <= 1) return orderedEntities;
-
-            for (var i = 1; i < sortQueries.Count; i++)
-                orderedEntities = orderedEntities.Sort(sortQueries[i]);
-
-            return orderedEntities;
+            return entities.Sort(sortQueries);
         }
 
         public virtual async Task<TEntity> GetAsync(TId id)
diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index ee6b4451c5..9ba37057a7 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -2,15 +2,30 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
-using System.Reflection;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Query;
+using JsonApiDotNetCore.Services;
 
 namespace JsonApiDotNetCore.Extensions
 {
     // ReSharper disable once InconsistentNaming
     public static class IQueryableExtensions
     {
+        public static IQueryable<TSource> Sort<TSource>(this IQueryable<TSource> source, List<SortQuery> sortQueries)
+        {
+            if (sortQueries == null || sortQueries.Count == 0)
+                return source;
+
+            var orderedEntities = source.Sort(sortQueries[0]);
+
+            if (sortQueries.Count <= 1) return orderedEntities;
+
+            for (var i = 1; i < sortQueries.Count; i++)
+                orderedEntities = orderedEntities.Sort(sortQueries[i]);
+
+            return orderedEntities;
+        }
+
         public static IOrderedQueryable<TSource> Sort<TSource>(this IQueryable<TSource> source, SortQuery sortQuery)
         {
             return sortQuery.Direction == SortDirection.Descending 

From 872b74b1fc10dc597574d66580cf6a890b2b6f1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20H=C3=BCbner?= <sven.huebner@zeiss.com>
Date: Tue, 2 Jan 2018 10:53:18 +0100
Subject: [PATCH 078/227] moved Page into an IQueryable extension method

---
 .../Data/DefaultEntityRepository.cs           | 31 +++----
 .../Extensions/IQueryableExtensions.cs        | 16 ++++
 .../Acceptance/Spec/PagingTests.cs            | 34 ++++----
 .../Data/DefaultEntityRepository_Tests.cs     | 80 ++++++++++++++++++-
 4 files changed, 123 insertions(+), 38 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index b31f4abaed..ed090b8f71 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -146,27 +146,22 @@ public virtual IQueryable<TEntity> Include(IQueryable<TEntity> entities, string
 
         public virtual async Task<IEnumerable<TEntity>> PageAsync(IQueryable<TEntity> entities, int pageSize, int pageNumber)
         {
-            if (pageSize > 0)
+            if (pageNumber >= 0)
             {
-                if (pageNumber == 0)
-                    pageNumber = 1;
-
-                if (pageNumber > 0)
-                    return await entities
-                        .Skip((pageNumber - 1) * pageSize)
-                        .Take(pageSize)
-                        .ToListAsync();
-                else // page from the end of the set                   
-                    return (await entities
-                        .OrderByDescending(t => t.Id)
-                        .Skip((Math.Abs(pageNumber) - 1) * pageSize)
-                        .Take(pageSize)
-                        .ToListAsync())
-                        .OrderBy(t => t.Id)
-                        .ToList();
+                return await entities.PageForward(pageSize, pageNumber).ToListAsync();
             }
 
-            return await entities.ToListAsync();
+            // since EntityFramework does not support IQueryable.Reverse(), we need to know the number of queried entities
+            int numberOfEntities = await this.CountAsync(entities);
+
+            // may be negative
+            int virtualFirstIndex = numberOfEntities - pageSize * Math.Abs(pageNumber);
+            int numberOfElementsInPage = Math.Min(pageSize, virtualFirstIndex + pageSize);
+
+            return await entities
+                    .Skip(virtualFirstIndex)
+                    .Take(numberOfElementsInPage)
+                    .ToListAsync();
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index 9ba37057a7..587a295fa0 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -216,5 +216,21 @@ public static IQueryable<TSource> Select<TSource>(this IQueryable<TSource> sourc
                 Expression.Call(typeof(Queryable), "Select", new[] { sourceType, resultType },
                 source.Expression, Expression.Quote(selector)));
         }
+
+        public static IQueryable<T> PageForward<T>(this IQueryable<T> source, int pageSize, int pageNumber)
+        {
+            if (pageSize > 0)
+            {
+                if (pageNumber == 0)
+                    pageNumber = 1;
+
+                if (pageNumber > 0)
+                    return source
+                        .Skip((pageNumber - 1) * pageSize)
+                        .Take(pageSize);
+            }
+
+            return source;
+        }
     }
 }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
index 02dbd019e0..7d8401f78d 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
@@ -1,7 +1,9 @@
+using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
 using Bogus;
+using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExample.Models;
@@ -50,7 +52,7 @@ public async Task Can_Paginate_TodoItems_From_Start() {
             const int expectedEntitiesPerPage = 2;
             var totalCount = expectedEntitiesPerPage * 2;
             var person = new Person();
-            var todoItems = _todoItemFaker.Generate(totalCount);
+            var todoItems = _todoItemFaker.Generate(totalCount).ToList();
 
             foreach (var todoItem in todoItems)
                 todoItem.Owner = person;
@@ -70,12 +72,8 @@ public async Task Can_Paginate_TodoItems_From_Start() {
             var body = await response.Content.ReadAsStringAsync();
             var deserializedBody = GetService<IJsonApiDeSerializer>().DeserializeList<TodoItem>(body);
 
-            Assert.NotEmpty(deserializedBody);
-            Assert.Equal(expectedEntitiesPerPage, deserializedBody.Count);
-
-            var expectedTodoItems = Context.TodoItems.Take(2);
-            foreach (var todoItem in expectedTodoItems)
-                Assert.NotNull(deserializedBody.SingleOrDefault(t => t.Id == todoItem.Id));
+            var expectedTodoItems = new[] { todoItems[0], todoItems[1] };
+            Assert.Equal(expectedTodoItems, deserializedBody, new IdComparer<TodoItem>());
         }
 
         [Fact]
@@ -84,7 +82,7 @@ public async Task Can_Paginate_TodoItems_From_End() {
             const int expectedEntitiesPerPage = 2;
             var totalCount = expectedEntitiesPerPage * 2;
             var person = new Person();
-            var todoItems = _todoItemFaker.Generate(totalCount);
+            var todoItems = _todoItemFaker.Generate(totalCount).ToList();
 
             foreach (var todoItem in todoItems)
                 todoItem.Owner = person;
@@ -104,18 +102,16 @@ public async Task Can_Paginate_TodoItems_From_End() {
             var body = await response.Content.ReadAsStringAsync();
             var deserializedBody = GetService<IJsonApiDeSerializer>().DeserializeList<TodoItem>(body);
 
-            Assert.NotEmpty(deserializedBody);
-            Assert.Equal(expectedEntitiesPerPage, deserializedBody.Count);
+            var expectedTodoItems = new[] { todoItems[totalCount - 2], todoItems[totalCount - 1] };
+            Assert.Equal(expectedTodoItems, deserializedBody, new IdComparer<TodoItem>());
+        }
 
-            var expectedTodoItems = Context.TodoItems
-                .OrderByDescending(t => t.Id)
-                .Take(2)
-                .ToList()
-                .OrderBy(t => t.Id)
-                .ToList();
+        private class IdComparer<T> : IEqualityComparer<T>
+            where T : IIdentifiable
+        {
+            public bool Equals(T x, T y) => x?.StringId == y?.StringId;
 
-            for (int i = 0; i < expectedEntitiesPerPage; i++)
-                Assert.Equal(expectedTodoItems[i].Id, deserializedBody[i].Id);
+            public int GetHashCode(T obj) => obj?.StringId?.GetHashCode() ?? 0;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/test/UnitTests/Data/DefaultEntityRepository_Tests.cs b/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
index 50d24409f8..a8ec56fe9c 100644
--- a/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
+++ b/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
@@ -13,7 +13,8 @@
 using Microsoft.Extensions.Logging;
 using JsonApiDotNetCore.Services;
 using System.Threading.Tasks;
-
+using System.Linq;
+
 namespace UnitTests.Data
 {
     public class DefaultEntityRepository_Tests : JsonApiControllerMixin
@@ -93,6 +94,83 @@ private DefaultEntityRepository<TodoItem> GetRepository()
                 _loggFactoryMock.Object,
                 _jsonApiContextMock.Object,
                 _contextResolverMock.Object);
+        }
+
+        [Theory]
+        [InlineData(0)]
+        [InlineData(-1)]
+        [InlineData(-10)]
+        public async Task Page_When_PageSize_Is_NonPositive_Does_Nothing(int pageSize)
+        {
+            var todoItems = DbSetMock.Create(TodoItems(2, 3, 1)).Object;
+            var repository = GetRepository();
+
+            var result = await repository.PageAsync(todoItems, pageSize, 3);
+
+            Assert.Equal(TodoItems(2, 3, 1), result, new IdComparer<TodoItem>());
+        }
+
+        [Fact]
+        public async Task Page_When_PageNumber_Is_Zero_Pretends_PageNumber_Is_One()
+        {
+            var todoItems = DbSetMock.Create(TodoItems(2, 3, 1)).Object;
+            var repository = GetRepository();
+
+            var result = await repository.PageAsync(todoItems, 1, 0);
+
+            Assert.Equal(TodoItems(2), result, new IdComparer<TodoItem>());
+        }
+
+        [Fact]
+        public async Task Page_When_PageNumber_Of_PageSize_Does_Not_Exist_Return_Empty_Queryable()
+        {
+            var todoItems = DbSetMock.Create(TodoItems(2, 3, 1)).Object;
+            var repository = GetRepository();
+
+            var result = await repository.PageAsync(todoItems, 2, 3);
+
+            Assert.Empty(result);
+        }
+
+        [Theory]
+        [InlineData(3, 2, new[] { 4, 5, 6 })]
+        [InlineData(8, 2, new[] { 9 })]
+        [InlineData(20, 1, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })]
+        public async Task Page_When_PageNumber_Is_Positive_Returns_PageNumberTh_Page_Of_Size_PageSize(int pageSize, int pageNumber, int[] expectedResult)
+        {
+            var todoItems = DbSetMock.Create(TodoItems(1, 2, 3, 4, 5, 6, 7, 8, 9)).Object;
+            var repository = GetRepository();
+
+            var result = await repository.PageAsync(todoItems, pageSize, pageNumber);
+
+            Assert.Equal(TodoItems(expectedResult), result, new IdComparer<TodoItem>());
+        }
+
+        [Theory]
+        [InlineData(6, -1, new[] { 4, 5, 6, 7, 8, 9 })]
+        [InlineData(6, -2, new[] { 1, 2, 3 })]
+        [InlineData(20, -1, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })]
+        public async Task Page_When_PageNumber_Is_Negative_Returns_PageNumberTh_Page_From_End(int pageSize, int pageNumber, int[] expectedIds)
+        {
+            var todoItems = DbSetMock.Create(TodoItems(1, 2, 3, 4, 5, 6, 7, 8, 9)).Object;
+            var repository = GetRepository();
+
+            var result = await repository.PageAsync(todoItems, pageSize, pageNumber);
+            
+            Assert.Equal(TodoItems(expectedIds), result, new IdComparer<TodoItem>());
+        }
+
+        private static TodoItem[] TodoItems(params int[] ids)
+        {
+            return ids.Select(id => new TodoItem { Id = id }).ToArray();
+        }
+
+        private class IdComparer<T> : IEqualityComparer<T>
+            where T : IIdentifiable
+        {
+            public bool Equals(T x, T y) => x?.StringId == y?.StringId;
+
+            public int GetHashCode(T obj) => obj?.StringId?.GetHashCode() ?? 0;
         }
     }
 }

From 916e03c2e7b02224df6e2ecb51561f0b66075c66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20H=C3=BCbner?= <sven.huebner@zeiss.com>
Date: Tue, 2 Jan 2018 11:07:26 +0100
Subject: [PATCH 079/227] moved Filter into an IQueryable extension method

---
 src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs |  8 +-------
 .../Extensions/IQueryableExtensions.cs                | 11 +++++++++++
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index ed090b8f71..6c270c7396 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -58,13 +58,7 @@ public virtual IQueryable<TEntity> Get()
 
         public virtual IQueryable<TEntity> Filter(IQueryable<TEntity> entities, FilterQuery filterQuery)
         {
-            if (filterQuery == null)
-                return entities;
-
-            if (filterQuery.IsAttributeOfRelationship)
-                return entities.Filter(new RelatedAttrFilterQuery(_jsonApiContext, filterQuery));
-
-            return entities.Filter(new AttrFilterQuery(_jsonApiContext, filterQuery));
+            return entities.Filter(_jsonApiContext, filterQuery);
         }
 
         public virtual IQueryable<TEntity> Sort(IQueryable<TEntity> entities, List<SortQuery> sortQueries)
diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index 587a295fa0..6bbb1115b2 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -77,6 +77,17 @@ private static IOrderedQueryable<TSource> CallGenericOrderMethod<TSource>(IQuery
             return (IOrderedQueryable<TSource>)result;
         }
 
+        public static IQueryable<TSource> Filter<TSource>(this IQueryable<TSource> source, IJsonApiContext jsonApiContext, FilterQuery filterQuery)
+        {
+            if (filterQuery == null)
+                return source;
+
+            if (filterQuery.IsAttributeOfRelationship)
+                return source.Filter(new RelatedAttrFilterQuery(jsonApiContext, filterQuery));
+
+            return source.Filter(new AttrFilterQuery(jsonApiContext, filterQuery));
+        }
+
         public static IQueryable<TSource> Filter<TSource>(this IQueryable<TSource> source, AttrFilterQuery filterQuery)
         {
             if (filterQuery == null)

From 0209baef26fbf205d5e18f596c2519202a90f894 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20H=C3=BCbner?= <sven.huebner@zeiss.com>
Date: Tue, 2 Jan 2018 13:49:48 +0100
Subject: [PATCH 080/227] removed dependency on query realization from
 EntityResourceService

---
 .../Data/DefaultEntityRepository.cs               | 15 +++++++++++++++
 .../Data/IEntityReadRepository.cs                 |  6 ++++++
 .../Services/EntityResourceService.cs             |  7 +++----
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index 6c270c7396..45627fd1a6 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -157,5 +157,20 @@ public virtual async Task<IEnumerable<TEntity>> PageAsync(IQueryable<TEntity> en
                     .Take(numberOfElementsInPage)
                     .ToListAsync();
         }
+
+        public async Task<int> CountAsync(IQueryable<TEntity> entities)
+        {
+            return await entities.CountAsync();
+        }
+
+        public Task<TEntity> FirstOrDefaultAsync(IQueryable<TEntity> entities)
+        {
+            return entities.FirstOrDefaultAsync();
+        }
+
+        public async Task<IReadOnlyList<TEntity>> ToListAsync(IQueryable<TEntity> entities)
+        {
+            return await entities.ToListAsync();
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Data/IEntityReadRepository.cs b/src/JsonApiDotNetCore/Data/IEntityReadRepository.cs
index aad16a9efc..a86b7334a9 100644
--- a/src/JsonApiDotNetCore/Data/IEntityReadRepository.cs
+++ b/src/JsonApiDotNetCore/Data/IEntityReadRepository.cs
@@ -27,5 +27,11 @@ public interface IEntityReadRepository<TEntity, in TId>
         Task<TEntity> GetAsync(TId id);
 
         Task<TEntity> GetAndIncludeAsync(TId id, string relationshipName);
+
+        Task<int> CountAsync(IQueryable<TEntity> entities);
+
+        Task<TEntity> FirstOrDefaultAsync(IQueryable<TEntity> entities);
+
+        Task<IReadOnlyList<TEntity>> ToListAsync(IQueryable<TEntity> entities);
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index cc1ba897e1..7cf640542a 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -5,7 +5,6 @@
 using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
-using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.Logging;
 
 namespace JsonApiDotNetCore.Services
@@ -50,7 +49,7 @@ public virtual async Task<IEnumerable<T>> GetAsync()
                 entities = IncludeRelationships(entities, _jsonApiContext.QuerySet.IncludedRelationships);
 
             if (_jsonApiContext.Options.IncludeTotalRecordCount)
-                _jsonApiContext.PageManager.TotalRecords = await entities.CountAsync();
+                _jsonApiContext.PageManager.TotalRecords = await _entities.CountAsync(entities);
 
             // pagination should be done last since it will execute the query
             var pagedEntities = await ApplyPageQueryAsync(entities);
@@ -72,12 +71,12 @@ private bool ShouldIncludeRelationships()
 
         private async Task<T> GetWithRelationshipsAsync(TId id)
         {
-            var query = _entities.Get();
+            var query = _entities.Get().Where(e => e.Id.Equals(id));
             _jsonApiContext.QuerySet.IncludedRelationships.ForEach(r =>
             {
                 query = _entities.Include(query, r);
             });
-            return await query.FirstOrDefaultAsync(e => e.Id.Equals(id));
+            return await _entities.FirstOrDefaultAsync(query);
         }
 
         public virtual async Task<object> GetRelationshipsAsync(TId id, string relationshipName)

From 70cb94c38554a592cdde8f77f419dbc6aaca71db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20H=C3=BCbner?= <sven.huebner@zeiss.com>
Date: Wed, 3 Jan 2018 13:41:20 +0100
Subject: [PATCH 081/227] realize query when there is no paging in
 EntityResourceService.ApplyPageQueryAsync

---
 src/JsonApiDotNetCore/Services/EntityResourceService.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index 7cf640542a..c0b4847f13 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -165,7 +165,7 @@ private async Task<IEnumerable<T>> ApplyPageQueryAsync(IQueryable<T> entities)
         {
             var pageManager = _jsonApiContext.PageManager;
             if (!pageManager.IsPaginated)
-                return entities;
+                return await _entities.ToListAsync(entities);
 
             _logger?.LogInformation($"Applying paging query. Fetching page {pageManager.CurrentPage} with {pageManager.PageSize} entities");
 

From 4425c71903a09db3fe3fa740378c6ae8a3b7e640 Mon Sep 17 00:00:00 2001
From: Lauri Heiskanen <lauri.heiskanen@nimble.fi>
Date: Thu, 25 Jan 2018 10:59:21 +0200
Subject: [PATCH 082/227] feat/#226: Support for omitting null valued
 attributes from responses

    - NullAttributeResponseBehavior option for configuration
    - Support for global defaults
    - Support for client override using a query string parameter
---
 JsonApiDotnetCore.sln                         | 28 +++----
 .../Builders/DocumentBuilder.cs               | 31 ++++----
 .../Builders/DocumentBuilderOptions.cs        | 16 ++++
 .../DocumentBuilderOptionsProvider.cs         | 33 +++++++++
 .../IDocumentBuilderOptionsProvider.cs        | 11 +++
 .../Configuration/JsonApiOptions.cs           |  4 +
 .../NullAttributeResponseBehavior.cs          | 19 +++++
 .../IServiceCollectionExtensions.cs           |  1 +
 .../Serialization/JsonApiDeSerializer.cs      |  3 +-
 .../Services/IJsonApiContext.cs               |  2 +
 .../Services/JsonApiContext.cs                |  1 +
 .../DocumentBuilderBehaviour_Tests.cs         | 73 +++++++++++++++++++
 .../Builders/DocumentBuilder_Tests.cs         | 29 ++++++++
 .../Serialization/JsonApiDeSerializerTests.cs | 50 ++++++++++++-
 14 files changed, 272 insertions(+), 29 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs
 create mode 100644 src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs
 create mode 100644 src/JsonApiDotNetCore/Builders/IDocumentBuilderOptionsProvider.cs
 create mode 100644 src/JsonApiDotNetCore/Configuration/NullAttributeResponseBehavior.cs
 create mode 100644 test/UnitTests/Builders/DocumentBuilderBehaviour_Tests.cs

diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index 385fa4d6ad..0425e09f96 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -1,6 +1,6 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
-VisualStudioVersion = 15.0.26730.10
+VisualStudioVersion = 15.0.27004.2009
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\JsonApiDotNetCore\JsonApiDotNetCore.csproj", "{C0EC9E70-EB2E-436F-9D94-FA16FA774123}"
 EndProject
@@ -30,7 +30,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReportsExample", "src\Examp
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{076E1AE4-FD25-4684-B826-CAAE37FEA0AA}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "benchmarks\Benchmarks.csproj", "{1F604666-BB0F-413E-922D-9D37C6073285}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "benchmarks\Benchmarks.csproj", "{1F604666-BB0F-413E-922D-9D37C6073285}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -110,22 +110,22 @@ Global
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Debug|x86.Build.0 = Debug|Any CPU
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|Any CPU.Build.0 = Release|Any CPU
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.ActiveCfg = Release|x64
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|x64
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|x86
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|x86
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.ActiveCfg = Release|Any CPU
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|Any CPU
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|Any CPU
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x64.ActiveCfg = Debug|x64
-		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x64.Build.0 = Debug|x64
-		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x86.ActiveCfg = Debug|x86
-		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x86.Build.0 = Debug|x86
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x64.Build.0 = Debug|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x86.Build.0 = Debug|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|Any CPU.Build.0 = Release|Any CPU
-		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x64.ActiveCfg = Release|x64
-		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x64.Build.0 = Release|x64
-		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.ActiveCfg = Release|x86
-		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.Build.0 = Release|x86
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x64.ActiveCfg = Release|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x64.Build.0 = Release|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.ActiveCfg = Release|Any CPU
+		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index ac7e1b3ade..9e2517305e 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -13,18 +13,14 @@ public class DocumentBuilder : IDocumentBuilder
         private readonly IJsonApiContext _jsonApiContext;
         private readonly IContextGraph _contextGraph;
         private readonly IRequestMeta _requestMeta;
+        private readonly DocumentBuilderOptions _documentBuilderOptions; 
 
-        public DocumentBuilder(IJsonApiContext jsonApiContext)
-        {
-            _jsonApiContext = jsonApiContext;
-            _contextGraph = jsonApiContext.ContextGraph;
-        }
-
-        public DocumentBuilder(IJsonApiContext jsonApiContext, IRequestMeta requestMeta)
+        public DocumentBuilder(IJsonApiContext jsonApiContext, IRequestMeta requestMeta=null, IDocumentBuilderOptionsProvider documentBuilderOptionsProvider=null)
         {
             _jsonApiContext = jsonApiContext;
             _contextGraph = jsonApiContext.ContextGraph;
             _requestMeta = requestMeta;
+            _documentBuilderOptions = documentBuilderOptionsProvider?.GetDocumentBuilderOptions() ?? new DocumentBuilderOptions(); ;
         }
 
         public Document Build(IIdentifiable entity)
@@ -118,8 +114,11 @@ private DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
 
             contextEntity.Attributes.ForEach(attr =>
             {
-                if(ShouldIncludeAttribute(attr))
-                    data.Attributes.Add(attr.PublicAttributeName, attr.GetValue(entity));
+                var attributeValue = attr.GetValue(entity);
+                if (ShouldIncludeAttribute(attr, attributeValue))
+                {
+                    data.Attributes.Add(attr.PublicAttributeName, attributeValue);
+                }
             });
 
             if (contextEntity.Relationships.Count > 0)
@@ -128,11 +127,17 @@ private DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
             return data;
         }
 
-        private bool ShouldIncludeAttribute(AttrAttribute attr)
+        private bool ShouldIncludeAttribute(AttrAttribute attr, object attributeValue)
+        {
+            return !OmitNullValuedAttribute(attr, attributeValue)
+                   && ((_jsonApiContext.QuerySet == null
+                       || _jsonApiContext.QuerySet.Fields.Count == 0)
+                       || _jsonApiContext.QuerySet.Fields.Contains(attr.InternalAttributeName));
+        }
+
+        private bool OmitNullValuedAttribute(AttrAttribute attr, object attributeValue)
         {
-            return (_jsonApiContext.QuerySet == null 
-                || _jsonApiContext.QuerySet.Fields.Count == 0 
-                || _jsonApiContext.QuerySet.Fields.Contains(attr.InternalAttributeName));
+            return attributeValue == null && _documentBuilderOptions.OmitNullValuedAttributes;
         }
 
         private void AddRelationships(DocumentData data, ContextEntity contextEntity, IIdentifiable entity)
diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs
new file mode 100644
index 0000000000..ec19977313
--- /dev/null
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JsonApiDotNetCore.Builders
+{
+    public struct DocumentBuilderOptions 
+    {
+        public DocumentBuilderOptions(bool omitNullValuedAttributes = false)
+        {
+            this.OmitNullValuedAttributes = omitNullValuedAttributes;
+        }
+
+        public bool OmitNullValuedAttributes { get; private set; }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs
new file mode 100644
index 0000000000..af7fb78d7c
--- /dev/null
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Http;
+
+namespace JsonApiDotNetCore.Builders
+{
+    public class DocumentBuilderOptionsProvider : IDocumentBuilderOptionsProvider
+    {
+        private readonly IJsonApiContext _jsonApiContext;
+        private readonly IHttpContextAccessor _httpContextAccessor;
+
+        public DocumentBuilderOptionsProvider(IJsonApiContext jsonApiContext, IHttpContextAccessor httpContextAccessor)
+        {
+            _jsonApiContext = jsonApiContext;
+            _httpContextAccessor = httpContextAccessor;
+        }
+
+        public DocumentBuilderOptions GetDocumentBuilderOptions()
+        {
+            var nullAttributeResponseBehaviorConfig = this._jsonApiContext.Options.NullAttributeResponseBehavior;
+            if (nullAttributeResponseBehaviorConfig.AllowClientOverride && _httpContextAccessor.HttpContext.Request.Query.TryGetValue("omitNullValuedAttributes", out var omitNullValuedAttributesQs))
+            {
+                if (bool.TryParse(omitNullValuedAttributesQs, out var omitNullValuedAttributes))
+                {
+                    return new DocumentBuilderOptions(omitNullValuedAttributes);                                
+                }
+            }
+            return new DocumentBuilderOptions(this._jsonApiContext.Options.NullAttributeResponseBehavior.OmitNullValuedAttributes);
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Builders/IDocumentBuilderOptionsProvider.cs b/src/JsonApiDotNetCore/Builders/IDocumentBuilderOptionsProvider.cs
new file mode 100644
index 0000000000..d8effd4fe3
--- /dev/null
+++ b/src/JsonApiDotNetCore/Builders/IDocumentBuilderOptionsProvider.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JsonApiDotNetCore.Builders
+{
+    public interface IDocumentBuilderOptionsProvider
+    {
+        DocumentBuilderOptions GetDocumentBuilderOptions(); 
+    }
+}
diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index 26e16b0741..f074940d9c 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -17,6 +17,7 @@ public class JsonApiOptions
         public IContextGraph ContextGraph { get; set; }
         public bool RelativeLinks { get; set; }
         public bool AllowCustomQueryParameters { get; set; }
+        public NullAttributeResponseBehavior NullAttributeResponseBehavior { get; set; }
 
         [Obsolete("JsonContract resolver can now be set on SerializerSettings.")]
         public IContractResolver JsonContractResolver
@@ -29,6 +30,7 @@ public IContractResolver JsonContractResolver
             NullValueHandling = NullValueHandling.Ignore,
             ContractResolver = new DasherizedResolver()
         };
+
         internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder();
 
         public void BuildContextGraph<TContext>(Action<IContextGraphBuilder> builder) where TContext : DbContext
@@ -49,4 +51,6 @@ public void BuildContextGraph(Action<IContextGraphBuilder> builder)
             ContextGraph = ContextGraphBuilder.Build();
         }
     }
+
+    
 }
diff --git a/src/JsonApiDotNetCore/Configuration/NullAttributeResponseBehavior.cs b/src/JsonApiDotNetCore/Configuration/NullAttributeResponseBehavior.cs
new file mode 100644
index 0000000000..1b10140f5e
--- /dev/null
+++ b/src/JsonApiDotNetCore/Configuration/NullAttributeResponseBehavior.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JsonApiDotNetCore.Configuration
+{
+    public struct NullAttributeResponseBehavior
+    {
+        public NullAttributeResponseBehavior(bool omitNullValuedAttributes = false, bool allowClientOverride = false)
+        {
+            OmitNullValuedAttributes = omitNullValuedAttributes;
+            AllowClientOverride = allowClientOverride;
+        }
+
+        public bool OmitNullValuedAttributes { get; }
+        public bool AllowClientOverride { get; }
+        // ...
+    }
+}
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 1549e77e0f..d75ce26c59 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -112,6 +112,7 @@ public static void AddJsonApiInternals(
             services.AddScoped<IQueryAccessor, QueryAccessor>();
             services.AddScoped<IQueryParser, QueryParser>();
             services.AddScoped<IControllerContext, Services.ControllerContext>();
+            services.AddScoped<IDocumentBuilderOptionsProvider, DocumentBuilderOptionsProvider>();
         }
 
         public static void SerializeAsJsonApi(this MvcOptions options, JsonApiOptions jsonApiOptions)
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 1c0c5014f7..6fa02c90c4 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -29,6 +29,7 @@ public object Deserialize(string requestBody)
             try
             {
                 var document = JsonConvert.DeserializeObject<Document>(requestBody);
+                _jsonApiContext.DocumentMeta = document.Meta;
                 var entity = DocumentToObject(document.Data);
                 return entity;
             }
@@ -222,4 +223,4 @@ private object SetHasManyRelationship(object entity,
             return entity;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index ee7ee10a35..c16da81cfa 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -26,6 +26,8 @@ public interface IJsonApiContext
         Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; }
         Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
         Type ControllerType { get; set; }
+        Dictionary<string, object> DocumentMeta { get; set; }
+
         TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 5304d77b29..ef6b4159ee 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -50,6 +50,7 @@ public JsonApiContext(
         public Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; } = new Dictionary<AttrAttribute, object>();
         public Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; } = new Dictionary<RelationshipAttribute, object>();
         public Type ControllerType { get; set; }
+        public Dictionary<string, object> DocumentMeta { get; set; }
 
         public IJsonApiContext ApplyContext<T>(object controller)
         {
diff --git a/test/UnitTests/Builders/DocumentBuilderBehaviour_Tests.cs b/test/UnitTests/Builders/DocumentBuilderBehaviour_Tests.cs
new file mode 100644
index 0000000000..333950f95f
--- /dev/null
+++ b/test/UnitTests/Builders/DocumentBuilderBehaviour_Tests.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Http;
+using Moq;
+using Xunit;
+
+namespace UnitTests.Builders
+{
+    public class DocumentBuilderBehaviour_Tests
+    {
+
+        [Theory]
+        [InlineData(null, null, null, false)]
+        [InlineData(false, null, null, false)]
+        [InlineData(true, null, null, true)]
+        [InlineData(false, false, "true", false)]
+        [InlineData(false, true, "true", true)]
+        [InlineData(true, true, "false", false)]
+        [InlineData(true, false, "false", true)]
+        [InlineData(null, false, "false", false)]
+        [InlineData(null, false, "true", false)]
+        [InlineData(null, true, "true", true)]
+        [InlineData(null, true, "false", false)]
+        [InlineData(null, true, "foo", false)]
+        [InlineData(null, false, "foo", false)]
+        [InlineData(true, true, "foo", true)]
+        [InlineData(true, false, "foo", true)]
+        [InlineData(null, true, null, false)]
+        [InlineData(null, false, null, false)]
+        public void CheckNullBehaviorCombination(bool? omitNullValuedAttributes, bool? allowClientOverride, string clientOverride, bool omitsNulls)
+        {
+
+            NullAttributeResponseBehavior nullAttributeResponseBehavior; 
+            if (omitNullValuedAttributes.HasValue && allowClientOverride.HasValue)
+            {
+                nullAttributeResponseBehavior = new NullAttributeResponseBehavior(omitNullValuedAttributes.Value, allowClientOverride.Value);
+            }else if (omitNullValuedAttributes.HasValue)
+            {
+                nullAttributeResponseBehavior = new NullAttributeResponseBehavior(omitNullValuedAttributes.Value);
+            }else if
+                (allowClientOverride.HasValue)
+            {
+                nullAttributeResponseBehavior = new NullAttributeResponseBehavior(allowClientOverride: allowClientOverride.Value);
+            }
+            else
+            {
+                nullAttributeResponseBehavior = new NullAttributeResponseBehavior();
+            }
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupGet(m => m.Options)
+                .Returns(new JsonApiOptions() {NullAttributeResponseBehavior = nullAttributeResponseBehavior});
+
+            var httpContext = new DefaultHttpContext();
+            if (clientOverride != null)
+            {
+                httpContext.Request.QueryString = new QueryString($"?omitNullValuedAttributes={clientOverride}");
+            }
+            var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
+            httpContextAccessorMock.SetupGet(m => m.HttpContext).Returns(httpContext);
+
+            var sut = new DocumentBuilderOptionsProvider(jsonApiContextMock.Object, httpContextAccessorMock.Object);
+            var documentBuilderOptions = sut.GetDocumentBuilderOptions();
+
+            Assert.Equal(omitsNulls, documentBuilderOptions.OmitNullValuedAttributes);
+        }
+
+    }
+}
diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index 2cc4e7f7a3..7946efa058 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -16,10 +16,12 @@ public class DocumentBuilder_Tests
         private readonly Mock<IJsonApiContext> _jsonApiContextMock;
         private readonly PageManager _pageManager;
         private readonly JsonApiOptions _options;
+        private readonly Mock<IRequestMeta> _requestMetaMock;
 
         public DocumentBuilder_Tests()
         {
             _jsonApiContextMock = new Mock<IJsonApiContext>();
+            _requestMetaMock = new Mock<IRequestMeta>();
 
             _options = new JsonApiOptions();
 
@@ -141,11 +143,38 @@ public void Build_Can_Build_CustomIEnumerables()
             Assert.Equal(1, documents.Data.Count);
         }
 
+
+        [Theory]
+        [InlineData(null,null,true)]
+        [InlineData(false,null,true)]
+        [InlineData(true,null,false)]
+        [InlineData(null,"foo",true)]
+        [InlineData(false,"foo",true)]
+        [InlineData(true,"foo",true)]
+        public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
+            string attributeValue,
+            bool resultContainsAttribute)
+        {
+            var documentBuilderBehaviourMock = new Mock<IDocumentBuilderOptionsProvider>();
+            if (omitNullValuedAttributes.HasValue)
+            {
+                documentBuilderBehaviourMock.Setup(m => m.GetDocumentBuilderOptions())
+                    .Returns(new DocumentBuilderOptions(omitNullValuedAttributes.Value));
+            }
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, null, omitNullValuedAttributes.HasValue ? documentBuilderBehaviourMock.Object : null);
+            var document = documentBuilder.Build(new Model(){StringProperty = attributeValue});
+
+            Assert.Equal(resultContainsAttribute, document.Data.Attributes.ContainsKey("StringProperty"));
+        }
+
         private class Model : Identifiable
         {
             [HasOne("related-model", Link.None)]
             public RelatedModel RelatedModel { get; set; }
             public int RelatedModelId { get; set; }
+            [Attr("StringProperty")]
+            public string StringProperty { get; set; }
+
         }
 
         private class RelatedModel : Identifiable
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index 5096cbac31..1e20c0359e 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
@@ -271,6 +271,54 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Rel
             Assert.Equal(property, result.Property);
         }
 
+        [Fact]
+        public void Sets_The_DocumentMeta_Property_In_JsonApiContext()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<Independent>("independents");
+            contextGraphBuilder.AddResource<Dependent>("dependents");
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+
+            var property = Guid.NewGuid().ToString();
+            
+            var content = new Document
+            {   
+                Meta = new Dictionary<string, object>() { {"foo", "bar"}},
+                Data = new DocumentData
+                {
+                    Type = "independents",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object> { { "property", property }
+                    },
+                    // a common case for this is deserialization in unit tests
+                    Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } }
+                    }
+                }
+            };
+
+            var contentString = JsonConvert.SerializeObject(content);
+
+            // act
+            var result = deserializer.Deserialize<Independent>(contentString);
+
+            // assert
+            jsonApiContextMock.VerifySet(mock => mock.DocumentMeta = content.Meta);
+        }
+
+
         private class TestResource : Identifiable {
             [Attr("complex-member")]
             public ComplexType ComplexMember { get; set; }

From e828dc93011b68821f4c72eb6150f9a7b82341eb Mon Sep 17 00:00:00 2001
From: Lauri Heiskanen <lauri.heiskanen@nimble.fi>
Date: Mon, 29 Jan 2018 17:53:09 +0200
Subject: [PATCH 083/227] End to end tests for null valued attribute handling

---
 .../NullValuedAttributeHandlingTests.cs       | 106 ++++++++++++++++++
 .../IServiceCollectionExtensionsTests.cs      |   1 +
 2 files changed, 107 insertions(+)
 create mode 100644 test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs

diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs
new file mode 100644
index 0000000000..250ab80d30
--- /dev/null
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCoreExample;
+using JsonApiDotNetCoreExample.Data;
+using JsonApiDotNetCoreExample.Models;
+using Newtonsoft.Json;
+using Xunit;
+
+namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility
+{
+    [Collection("WebHostCollection")]
+    public class NullValuedAttributeHandlingTests : IAsyncLifetime
+    {
+        private readonly TestFixture<Startup> _fixture;
+        private readonly AppDbContext _dbContext;
+        private readonly TodoItem _todoItem;
+
+        public NullValuedAttributeHandlingTests(TestFixture<Startup> fixture)
+        {
+            _fixture = fixture;
+            _dbContext = fixture.GetService<AppDbContext>();
+            _todoItem = new TodoItem
+            {
+                Description = null,
+                Ordinal = 1,
+                CreatedDate = DateTime.Now,
+                AchievedDate = DateTime.Now.AddDays(2)
+            };
+            _todoItem = _dbContext.TodoItems.Add(_todoItem).Entity;
+        }
+
+        public async Task InitializeAsync()
+        {
+            await _dbContext.SaveChangesAsync();
+        }
+
+        public Task DisposeAsync()
+        {
+            return Task.CompletedTask;
+        }
+
+        [Theory]
+        [InlineData(null, null, null, false)]
+        [InlineData(true, null, null, true)]
+        [InlineData(false, true, "true", true)]
+        [InlineData(false, false, "true", false)]
+        [InlineData(true, true, "false", false)]
+        [InlineData(true, false, "false", true)]
+        [InlineData(null, false, "false", false)]
+        [InlineData(null, false, "true", false)]
+        [InlineData(null, true, "true", true)]
+        [InlineData(null, true, "false", false)]
+        [InlineData(null, true, "foo", false)]
+        [InlineData(null, false, "foo", false)]
+        [InlineData(true, true, "foo", true)]
+        [InlineData(true, false, "foo", true)]
+        [InlineData(null, true, null, false)]
+        [InlineData(null, false, null, false)]
+        public async Task CheckNullBehaviorCombination(bool? omitNullValuedAttributes, bool? allowClientOverride,
+            string clientOverride, bool omitsNulls)
+        {
+
+            // Override some null handling options
+            NullAttributeResponseBehavior nullAttributeResponseBehavior;
+            if (omitNullValuedAttributes.HasValue && allowClientOverride.HasValue)
+            {
+                nullAttributeResponseBehavior = new NullAttributeResponseBehavior(omitNullValuedAttributes.Value, allowClientOverride.Value);
+            }
+            else if (omitNullValuedAttributes.HasValue)
+            {
+                nullAttributeResponseBehavior = new NullAttributeResponseBehavior(omitNullValuedAttributes.Value);
+            }
+            else if (allowClientOverride.HasValue)
+            {
+                nullAttributeResponseBehavior = new NullAttributeResponseBehavior(allowClientOverride: allowClientOverride.Value);
+            }
+            else
+            {
+                nullAttributeResponseBehavior = new NullAttributeResponseBehavior();
+            }
+            var jsonApiOptions = _fixture.GetService<JsonApiOptions>();
+            jsonApiOptions.NullAttributeResponseBehavior = nullAttributeResponseBehavior;
+            jsonApiOptions.AllowCustomQueryParameters = true;
+
+            var httpMethod = new HttpMethod("GET");
+            var queryString = allowClientOverride.HasValue
+                ? $"?omitNullValuedAttributes={clientOverride}"
+                : "";
+            var route = $"/api/v1/todo-items/{_todoItem.Id}{queryString}"; 
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // act
+            var response = await _fixture.Client.SendAsync(request);
+            var body = await response.Content.ReadAsStringAsync();
+            var deserializeBody = JsonConvert.DeserializeObject<Document>(body);
+
+            // assert. does response contain a null valued attribute
+            Assert.Equal(omitsNulls, !deserializeBody.Data.Attributes.ContainsKey("description"));
+
+        }
+    }
+
+}
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs b/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
index 5d68306493..b654727a26 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
@@ -49,6 +49,7 @@ public void AddJsonApiInternals_Adds_All_Required_Services()
             Assert.NotNull(provider.GetService<IJsonApiReader>());
             Assert.NotNull(provider.GetService<IJsonApiDeSerializer>());
             Assert.NotNull(provider.GetService<IGenericProcessorFactory>());
+            Assert.NotNull(provider.GetService<IDocumentBuilderOptionsProvider>());
             Assert.NotNull(provider.GetService(typeof(GenericProcessor<TodoItem>)));
         }
     }

From f6a84eb413b711ab79fc80845e8f569eeb10560d Mon Sep 17 00:00:00 2001
From: Biarity <Biarity@outlook.com>
Date: Sun, 11 Feb 2018 17:20:24 +1000
Subject: [PATCH 084/227] Fix broken url for IResourceService

---
 docs/ResourceServices.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/ResourceServices.md b/docs/ResourceServices.md
index 28629d9e36..17e7763835 100644
--- a/docs/ResourceServices.md
+++ b/docs/ResourceServices.md
@@ -4,7 +4,7 @@ currentMenu: services
 
 # Resource Services
 
-The [IResourceService](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Services/IResourceService.cs) acts as a service layer between the controller and the data access
+The [IResourceService](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Services/Contract/IResourceService.cs) acts as a service layer between the controller and the data access
 layer. This allows you to customize it however you want and not be dependent upon Entity
 Framework. This is also a good place to implement custom business logic.
 
@@ -123,4 +123,4 @@ public class MyResourcesController : BaseJsonApiController<MyResource> {
     public override async Task<IActionResult>DeleteAsync(int id) 
         => await base.DeleteAsync(id);
 }
-```
\ No newline at end of file
+```

From 2374492e3ff21e459383873efffd20ade80354cd Mon Sep 17 00:00:00 2001
From: Biarity <Biarity@outlook.com>
Date: Sat, 10 Feb 2018 18:02:44 +1000
Subject: [PATCH 085/227] Update Pagination.md

---
 docs/Pagination.md | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/docs/Pagination.md b/docs/Pagination.md
index 6d645cac2b..7d70773757 100644
--- a/docs/Pagination.md
+++ b/docs/Pagination.md
@@ -13,3 +13,11 @@ The following query would set the page size to 10 and get page 2.
 
 If you would like pagination implemented by default, you can specify the page size
 when setting up the services:
+
+```C#
+public IServiceProvider ConfigureServices(IServiceCollection services) {
+    services.AddJsonApi<AppDbContext>(
+        opt => opt.DefaultPageSize = 10);
+    // ...
+}
+```

From 19e90b8fad1902ab763de451fcdb020006176cd1 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 17 Feb 2018 18:16:43 -0600
Subject: [PATCH 086/227] include stack traces when not in production

---
 .../Configuration/JsonApiOptions.cs           | 10 +++++
 .../IApplicationBuilderExtensions.cs          | 10 +++++
 .../Formatters/JsonApiWriter.cs               | 15 ++++---
 src/JsonApiDotNetCore/Internal/Error.cs       | 40 +++++++++++++++++--
 .../Internal/JsonApiException.cs              | 24 ++++++-----
 .../Internal/JsonApiExceptionFactory.cs       | 29 +++-----------
 .../JsonApiDotNetCore.csproj                  |  4 +-
 7 files changed, 83 insertions(+), 49 deletions(-)

diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index f074940d9c..8643e28326 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -10,6 +10,16 @@ namespace JsonApiDotNetCore.Configuration
 {
     public class JsonApiOptions
     {
+        /// <summary>
+        /// Whether or not stack traces should be serialized in Error objects
+        /// </summary>
+        public static bool DisableErrorStackTraces { get; set; }
+        
+        /// <summary>
+        /// Whether or not source URLs should be serialized in Error objects
+        /// </summary>
+        public static bool DisableErrorSource { get; set; }
+
         public string Namespace { get; set; }
         public int DefaultPageSize { get; set; }
         public bool IncludeTotalRecordCount { get; set; }
diff --git a/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs b/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs
index c3d7ba2ee7..651fbb44aa 100644
--- a/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs
@@ -1,5 +1,7 @@
+using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Middleware;
 using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
 
 namespace JsonApiDotNetCore.Extensions
 {
@@ -8,6 +10,14 @@ public static class IApplicationBuilderExtensions
     {
         public static IApplicationBuilder UseJsonApi(this IApplicationBuilder app, bool useMvc = true)
         {
+            var environment = (IHostingEnvironment)app.ApplicationServices.GetService(typeof(IHostingEnvironment));
+
+            if(environment.IsProduction())
+            {
+                JsonApiOptions.DisableErrorStackTraces = true;
+                JsonApiOptions.DisableErrorSource = true;
+            }
+
             app.UseMiddleware<RequestMiddleware>();
 
             if (useMvc)
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs
index d644def66d..fcf0ac7850 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs
@@ -26,8 +26,6 @@ public async Task WriteAsync(OutputFormatterWriteContext context)
             if (context == null)
                 throw new ArgumentNullException(nameof(context));
 
-            _logger?.LogInformation("Formatting response as JSONAPI");
-
             var response = context.HttpContext.Response;
             using (var writer = context.WriterFactory(response.Body, Encoding.UTF8))
             {
@@ -40,9 +38,7 @@ public async Task WriteAsync(OutputFormatterWriteContext context)
                 catch (Exception e)
                 {
                     _logger?.LogError(new EventId(), e, "An error ocurred while formatting the response");
-                    var errors = new ErrorCollection();
-                    errors.Add(new Error("400", e.Message));
-                    responseContent = errors.GetJson();
+                    responseContent = GetErrorResponse(e);
                     response.StatusCode = 400;
                 }
 
@@ -51,9 +47,12 @@ public async Task WriteAsync(OutputFormatterWriteContext context)
             }
         }
 
-        private string GetResponseBody(object responseObject)
+        private string GetResponseBody(object responseObject) => _serializer.Serialize(responseObject);
+        private string GetErrorResponse(Exception e)
         {
-            return _serializer.Serialize(responseObject);
-        }        
+            var errors = new ErrorCollection();
+            errors.Add(new Error(400, e.Message, ErrorMeta.FromException(e)));
+            return errors.GetJson();
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Error.cs b/src/JsonApiDotNetCore/Internal/Error.cs
index 0443e1edb7..999611d79e 100644
--- a/src/JsonApiDotNetCore/Internal/Error.cs
+++ b/src/JsonApiDotNetCore/Internal/Error.cs
@@ -1,4 +1,6 @@
 using System;
+using System.Diagnostics;
+using JsonApiDotNetCore.Configuration;
 using Newtonsoft.Json;
 
 namespace JsonApiDotNetCore.Internal
@@ -8,30 +10,40 @@ public class Error
         public Error()
         { }
         
-        public Error(string status, string title)
+        [Obsolete("Use Error constructors with int typed status")]
+        public Error(string status, string title, ErrorMeta meta = null, string source = null)
         {
             Status = status;
             Title = title;
+            Meta = meta;
+            Source = source;
         }
 
-        public Error(int status, string title)
+        public Error(int status, string title, ErrorMeta meta = null, string source = null)
         {
             Status = status.ToString();
             Title = title;
+            Meta = meta;
+            Source = source;
         }
 
-        public Error(string status, string title, string detail)
+        [Obsolete("Use Error constructors with int typed status")]
+        public Error(string status, string title, string detail, ErrorMeta meta = null, string source = null)
         {
             Status = status;
             Title = title;
             Detail = detail;
+            Meta = meta;
+            Source = source;
         }
 
-        public Error(int status, string title, string detail)
+        public Error(int status, string title, string detail, ErrorMeta meta = null, string source = null)
         {
             Status = status.ToString();
             Title = title;
             Detail = detail;
+            Meta = meta;
+            Source = source;
         }
         
         [JsonProperty("title")]
@@ -45,5 +57,25 @@ public Error(int status, string title, string detail)
 
         [JsonIgnore]
         public int StatusCode => int.Parse(Status);
+
+        [JsonProperty("source")]
+        public string Source { get; set; }
+
+        [JsonProperty("meta")]
+        public ErrorMeta Meta { get; set; }
+
+        public bool ShouldSerializeMeta() => (JsonApiOptions.DisableErrorStackTraces == false);
+        public bool ShouldSerializeSource() => (JsonApiOptions.DisableErrorSource == false);
+    }
+
+    public class ErrorMeta
+    {
+        [JsonProperty("stackTrace")]
+        public string[] StackTrace { get; set; }
+
+        public static ErrorMeta FromException(Exception e) 
+            => new ErrorMeta { 
+                StackTrace = e.Demystify().ToString().Split(new[] { "\n"}, int.MaxValue, StringSplitOptions.RemoveEmptyEntries)
+            };
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/JsonApiException.cs b/src/JsonApiDotNetCore/Internal/JsonApiException.cs
index 9ce12fe428..5387154954 100644
--- a/src/JsonApiDotNetCore/Internal/JsonApiException.cs
+++ b/src/JsonApiDotNetCore/Internal/JsonApiException.cs
@@ -13,30 +13,29 @@ public JsonApiException(ErrorCollection errorCollection)
         }
 
         public JsonApiException(Error error)
-        : base(error.Title)
-            => _errors.Add(error);
+        : base(error.Title) => _errors.Add(error);
 
         [Obsolete("Use int statusCode overload instead")]
-        public JsonApiException(string statusCode, string message)
+        public JsonApiException(string statusCode, string message, string source = null)
         : base(message)
-            => _errors.Add(new Error(statusCode, message, null));
+            => _errors.Add(new Error(statusCode, message, null, GetMeta(), source));
 
         [Obsolete("Use int statusCode overload instead")]
-        public JsonApiException(string statusCode, string message, string detail)
+        public JsonApiException(string statusCode, string message, string detail, string source = null)
         : base(message)
-            => _errors.Add(new Error(statusCode, message, detail));
+            => _errors.Add(new Error(statusCode, message, detail, GetMeta(), source));
 
-        public JsonApiException(int statusCode, string message)
+        public JsonApiException(int statusCode, string message, string source = null)
         : base(message)
-            => _errors.Add(new Error(statusCode, message, null));
+            => _errors.Add(new Error(statusCode, message, null, GetMeta(), source));
 
-        public JsonApiException(int statusCode, string message, string detail)
+        public JsonApiException(int statusCode, string message, string detail, string source = null)
         : base(message)
-            => _errors.Add(new Error(statusCode, message, detail));
+            => _errors.Add(new Error(statusCode, message, detail, GetMeta(), source));
 
         public JsonApiException(int statusCode, string message, Exception innerException)
         : base(message, innerException)
-            => _errors.Add(new Error(statusCode, message, innerException.Message));
+            => _errors.Add(new Error(statusCode, message, innerException.Message, GetMeta(innerException)));
 
         public ErrorCollection GetError() => _errors;
 
@@ -53,5 +52,8 @@ public int GetStatusCode()
             
             return 500;
         }
+
+        private ErrorMeta GetMeta() => ErrorMeta.FromException(this);
+        private ErrorMeta GetMeta(Exception e) => ErrorMeta.FromException(e);
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs b/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
index 36b4969b1d..20ae9ebc62 100644
--- a/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
@@ -1,36 +1,17 @@
 using System;
-using System.Linq;
 
 namespace JsonApiDotNetCore.Internal
 {
     public static class JsonApiExceptionFactory
     {
-        private const string JsonApiException = nameof(JsonApiException);
-        private const string InvalidCastException = nameof(InvalidCastException);
-
         public static JsonApiException GetException(Exception exception)
         {
-            var exceptionType = exception.GetType().ToString().Split('.').Last();
-            switch(exceptionType)
-            {
-                case JsonApiException:
-                    return (JsonApiException)exception;
-                case InvalidCastException:
-                    return new JsonApiException(409, exception.Message);
-                default:
-                    return new JsonApiException(500, exception.Message, GetExceptionDetail(exception.InnerException));
-            }
-        }
+            var exceptionType = exception.GetType();
 
-        private static string GetExceptionDetail(Exception exception)
-        {
-            string detail = null;
-            while(exception != null)
-            {
-                detail = $"{detail}{exception.Message}; ";
-                exception = exception.InnerException;
-            }
-            return detail;
+            if(exceptionType == typeof(JsonApiException))
+                return (JsonApiException)exception;
+                
+            return new JsonApiException(500, exceptionType.Name, exception);
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 53c81b2ec1..61d725f6d8 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -15,11 +15,11 @@
     <RepositoryUrl>https://github.com/json-api-dotnet/JsonApiDotNetCore</RepositoryUrl>
   </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="Ben.Demystifier" Version="0.1.0" />
     <PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
     <PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftLoggingVersion)" />
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
   </ItemGroup>
-
-</Project>
+</Project>
\ No newline at end of file

From 9bdbb882abdc5d0dcba072fbccba310315628c49 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 18 Feb 2018 10:07:12 -0600
Subject: [PATCH 087/227] add static exception UnSupportedRequestMethod

---
 .../Controllers/BaseJsonApiController.cs        | 17 ++++++++---------
 src/JsonApiDotNetCore/Internal/Exceptions.cs    | 11 +++++++++++
 2 files changed, 19 insertions(+), 9 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Internal/Exceptions.cs

diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
index a10ea381de..760f8f8d56 100644
--- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
+++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
@@ -4,7 +4,6 @@
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
 
 namespace JsonApiDotNetCore.Controllers
 {
@@ -105,7 +104,7 @@ public BaseJsonApiController(
 
         public virtual async Task<IActionResult> GetAsync()
         {
-            if (_getAll == null) throw new JsonApiException(405, "Get requests are not supported");
+            if (_getAll == null) throw Exceptions.UnSupportedRequestMethod;
 
             var entities = await _getAll.GetAsync();
 
@@ -114,7 +113,7 @@ public virtual async Task<IActionResult> GetAsync()
 
         public virtual async Task<IActionResult> GetAsync(TId id)
         {
-            if (_getById == null) throw new JsonApiException(405, "Get by Id requests are not supported");
+            if (_getById == null) throw Exceptions.UnSupportedRequestMethod;
 
             var entity = await _getById.GetAsync(id);
 
@@ -126,7 +125,7 @@ public virtual async Task<IActionResult> GetAsync(TId id)
 
         public virtual async Task<IActionResult> GetRelationshipsAsync(TId id, string relationshipName)
         {
-            if (_getRelationships == null) throw new JsonApiException(405, "Get Relationships requests are not supported");
+            if (_getRelationships == null) throw Exceptions.UnSupportedRequestMethod;
 
             var relationship = await _getRelationships.GetRelationshipsAsync(id, relationshipName);
             if (relationship == null)
@@ -137,7 +136,7 @@ public virtual async Task<IActionResult> GetRelationshipsAsync(TId id, string re
 
         public virtual async Task<IActionResult> GetRelationshipAsync(TId id, string relationshipName)
         {
-            if (_getRelationship == null) throw new JsonApiException(405, "Get Relationship requests are not supported");
+            if (_getRelationship == null) throw Exceptions.UnSupportedRequestMethod;
 
             var relationship = await _getRelationship.GetRelationshipAsync(id, relationshipName);
 
@@ -146,7 +145,7 @@ public virtual async Task<IActionResult> GetRelationshipAsync(TId id, string rel
 
         public virtual async Task<IActionResult> PostAsync([FromBody] T entity)
         {
-            if (_create == null) throw new JsonApiException(405, "Post requests are not supported");
+            if (_create == null) throw Exceptions.UnSupportedRequestMethod;
 
             if (entity == null)
                 return UnprocessableEntity();
@@ -161,7 +160,7 @@ public virtual async Task<IActionResult> PostAsync([FromBody] T entity)
 
         public virtual async Task<IActionResult> PatchAsync(TId id, [FromBody] T entity)
         {
-            if (_update == null) throw new JsonApiException(405, "Patch requests are not supported");
+            if (_update == null) throw Exceptions.UnSupportedRequestMethod;
 
             if (entity == null)
                 return UnprocessableEntity();
@@ -176,7 +175,7 @@ public virtual async Task<IActionResult> PatchAsync(TId id, [FromBody] T entity)
 
         public virtual async Task<IActionResult> PatchRelationshipsAsync(TId id, string relationshipName, [FromBody] List<DocumentData> relationships)
         {
-            if (_updateRelationships == null) throw new JsonApiException(405, "Relationship Patch requests are not supported");
+            if (_updateRelationships == null) throw Exceptions.UnSupportedRequestMethod;
 
             await _updateRelationships.UpdateRelationshipsAsync(id, relationshipName, relationships);
 
@@ -185,7 +184,7 @@ public virtual async Task<IActionResult> PatchRelationshipsAsync(TId id, string
 
         public virtual async Task<IActionResult> DeleteAsync(TId id)
         {
-            if (_delete == null) throw new JsonApiException(405, "Delete requests are not supported");
+            if (_delete == null) throw Exceptions.UnSupportedRequestMethod;
 
             var wasDeleted = await _delete.DeleteAsync(id);
 
diff --git a/src/JsonApiDotNetCore/Internal/Exceptions.cs b/src/JsonApiDotNetCore/Internal/Exceptions.cs
new file mode 100644
index 0000000000..6c510e562b
--- /dev/null
+++ b/src/JsonApiDotNetCore/Internal/Exceptions.cs
@@ -0,0 +1,11 @@
+namespace JsonApiDotNetCore.Internal
+{
+    internal static class Exceptions
+    {
+        private const string DOCUMENTATION_URL = "https://json-api-dotnet.github.io/#/errors/";
+        private static string BuildUrl(string title) => DOCUMENTATION_URL + title;
+
+        public static JsonApiException UnSupportedRequestMethod { get; }  
+            = new JsonApiException(405, "Request method is not supported.", BuildUrl(nameof(UnSupportedRequestMethod)));
+    }
+}

From 0116376ccaeed684ec6ea35d36cd57490964e34a Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 18 Feb 2018 10:23:23 -0600
Subject: [PATCH 088/227] fix build issues and consolidate props definitions

---
 Directory.Build.props                         | 20 ++++--
 benchmarks/Benchmarks.csproj                  |  1 -
 build/dependencies.props                      | 11 ----
 .../JsonApiDotNetCoreExample.csproj           |  1 -
 .../NoEntityFrameworkExample.csproj           |  1 -
 .../OperationsExample.csproj                  | 65 +++++++++----------
 .../ReportsExample/ReportsExample.csproj      |  1 -
 .../IServiceCollectionExtensions.cs           |  2 -
 .../Internal/Generics/GenericProcessor.cs     |  2 +-
 .../JsonApiDotNetCore.csproj                  |  3 +-
 .../JsonApiDotNetCoreExampleTests.csproj      |  1 -
 .../NoEntityFrameworkTests.csproj             |  1 -
 .../OperationsExampleTests.csproj             | 14 ++--
 test/UnitTests/UnitTests.csproj               |  1 -
 14 files changed, 54 insertions(+), 70 deletions(-)
 delete mode 100644 build/dependencies.props

diff --git a/Directory.Build.props b/Directory.Build.props
index d3e19546db..cc81f65974 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,21 +1,27 @@
 <Project>
  
   <PropertyGroup>
+    <NetCoreAppVersion>netcoreapp2.0</NetCoreAppVersion>
     <NetStandardVersion>netstandard2.0</NetStandardVersion>
+
     <AspNetCoreVersion>2.0.1</AspNetCoreVersion>
-    <EFCoreVersion>2.0.1</EFCoreVersion>
+
     <MicrosoftLoggingVersion>2.0.0</MicrosoftLoggingVersion>
     <MicrosoftConfigurationVersion>2.0.0</MicrosoftConfigurationVersion>
+    <MicrosoftOptionsVersion>2.0.0</MicrosoftOptionsVersion>
+
+
+    <EFCoreVersion>2.0.1</EFCoreVersion>
+    <EFCoreToolsVersion>2.0.1</EFCoreToolsVersion>
+
+    <NpgsqlVersion>3.2.6</NpgsqlVersion>
+    <NpgsqlPostgreSQLVersion>2.0.0</NpgsqlPostgreSQLVersion>
+
     <TuplesVersion>4.4.0</TuplesVersion>
   </PropertyGroup>
  
  <!-- Test Project Dependencies -->
   <PropertyGroup>
-    <NetCoreAppVersion>netcoreapp2.0</NetCoreAppVersion>
-    <MicrosoftOptionsVersion>2.0.0</MicrosoftOptionsVersion>
-    <NpgsqlPostgreSQLVersion>2.0.0</NpgsqlPostgreSQLVersion>
-    <NpgsqlVersion>3.2.6</NpgsqlVersion>
-    <EFCoreToolsVersion>2.0.1</EFCoreToolsVersion>
     <TestSdkVersion>15.3.0-preview-20170427-09</TestSdkVersion>
     <TestHostVersion>1.1.2</TestHostVersion>
     <XUnitVersion>2.3.0-beta3-build3705</XUnitVersion>
@@ -23,4 +29,4 @@
     <MoqVersion>4.7.99</MoqVersion>
   </PropertyGroup>
  
-</Project>
\ No newline at end of file
+</Project>
diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj
index b5ff121826..1e8b227f3c 100644
--- a/benchmarks/Benchmarks.csproj
+++ b/benchmarks/Benchmarks.csproj
@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk">
-  <Import Project="..\build\dependencies.props" />
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
diff --git a/build/dependencies.props b/build/dependencies.props
deleted file mode 100644
index 0ef1b750a7..0000000000
--- a/build/dependencies.props
+++ /dev/null
@@ -1,11 +0,0 @@
-<Project>
-  <PropertyGroup>
-    <NetCoreAppVersion>netcoreapp2.0</NetCoreAppVersion>
-    <NetStandardVersion>netstandard2.0</NetStandardVersion>
-  </PropertyGroup>
-  <PropertyGroup>
-    <MoqVersion>4.7.10</MoqVersion>
-    <xUnitVersion>2.3.1</xUnitVersion>
-    <BogusVersion>8.0.1-beta-1</BogusVersion>
-  </PropertyGroup>
-</Project>
diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
index a2981cffd1..94e2a404a9 100755
--- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
+++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
-  <Import Project="..\..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <PreserveCompilationContext>true</PreserveCompilationContext>
diff --git a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
index 32506808fe..eed5f1b09e 100755
--- a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
+++ b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
-  <Import Project="..\..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
   </PropertyGroup>
diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj
index e033989925..48c2654722 100644
--- a/src/Examples/OperationsExample/OperationsExample.csproj
+++ b/src/Examples/OperationsExample/OperationsExample.csproj
@@ -1,33 +1,32 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
-
-  <PropertyGroup>
-    <TargetFramework>netcoreapp1.0</TargetFramework>
-    <PreserveCompilationContext>true</PreserveCompilationContext>
-    <AssemblyName>OperationsExample</AssemblyName>
-    <OutputType>Exe</OutputType>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="../../JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="1.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
-    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.1" />
-    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.2" />
-    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="1.1.0" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
-  </ItemGroup>
-
-</Project>
+<Project Sdk="Microsoft.NET.Sdk.Web">
+  <PropertyGroup>
+    <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
+    <PreserveCompilationContext>true</PreserveCompilationContext>
+    <AssemblyName>OperationsExample</AssemblyName>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="../../JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(AspNetCoreVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="$(MicrosoftConfigurationVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="$(MicrosoftConfigurationVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftConfigurationVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="$(MicrosoftConfigurationVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftLoggingVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftLoggingVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftLoggingVersion)" />
+    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="$(MicrosoftOptionsVersion)" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="$(EFCoreToolsVersion)" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="$(EFCoreToolsVersion)" />
+    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="$(EFCoreToolsVersion)" />
+  </ItemGroup>
+
+</Project>
diff --git a/src/Examples/ReportsExample/ReportsExample.csproj b/src/Examples/ReportsExample/ReportsExample.csproj
index f8f83e454c..bd4b402071 100644
--- a/src/Examples/ReportsExample/ReportsExample.csproj
+++ b/src/Examples/ReportsExample/ReportsExample.csproj
@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
-  <Import Project="..\..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
   </PropertyGroup>
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index e5569f4bc4..cd068ead6a 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -98,8 +98,6 @@ public static void AddJsonApiInternals(
             if (jsonApiOptions.EnabledExtensions.Contains(JsonApiExtension.Operations))
                 AddOperationServices(services);
 
-            services.AddScoped<IDbContextResolver, DbContextResolver>();
-
             services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
             services.AddScoped(typeof(IEntityRepository<,>), typeof(DefaultEntityRepository<,>));
 
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
index 5f9ffaca0f..8e5d17e56b 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
@@ -16,7 +16,7 @@ public interface IGenericProcessor
 
     public class GenericProcessor<T> : GenericProcessor<T, int> where T : class, IIdentifiable<int>
     {
-        public GenericProcessor(DbContext context) : base(context) { }
+        public GenericProcessor(IDbContextResolver contextResolver) : base(contextResolver) { }
     }
 
     public class GenericProcessor<T, TId> : IGenericProcessor where T : class, IIdentifiable<TId>
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 0d16b28e65..9fe109011b 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk">
-  <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <VersionPrefix>2.2.0</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
@@ -23,4 +22,4 @@
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
   </ItemGroup>
 
-</Project>
\ No newline at end of file
+</Project>
diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
index da92260546..90bd4050e7 100755
--- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk">
-  <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <IsPackable>false</IsPackable>
diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
index 5553a7c1eb..646cf9d538 100644
--- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
+++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk">
-  <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <PreserveCompilationContext>true</PreserveCompilationContext>
diff --git a/test/OperationsExampleTests/OperationsExampleTests.csproj b/test/OperationsExampleTests/OperationsExampleTests.csproj
index 18e795cb9e..a7727475bd 100644
--- a/test/OperationsExampleTests/OperationsExampleTests.csproj
+++ b/test/OperationsExampleTests/OperationsExampleTests.csproj
@@ -1,16 +1,16 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <TargetFramework>netcoreapp1.1</TargetFramework>
+    <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <IsPackable>false</IsPackable>
     <AssemblyName>OperationsExampleTests</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.1.3" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170427-09" />
-    <PackageReference Include="moq" Version="4.7.10" />
-    <PackageReference Include="xunit" Version="2.2.0" />
+    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="$(AspNetCoreVersion)" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
+    <PackageReference Include="moq" Version="$(MoqVersion)" />
+    <PackageReference Include="xunit" Version="$(XUnitVersion)" />
+    <PackageReference Include="Bogus" Version="$(BogusVersion)" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
-    <PackageReference Include="Bogus" Version="8.0.1-beta-1" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\src\Examples\OperationsExample\OperationsExample.csproj" />
@@ -20,4 +20,4 @@
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj
index 4848455eac..14a0d30e33 100644
--- a/test/UnitTests/UnitTests.csproj
+++ b/test/UnitTests/UnitTests.csproj
@@ -1,5 +1,4 @@
 <Project Sdk="Microsoft.NET.Sdk">
-  <Import Project="..\..\build\dependencies.props" />
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppVersion)</TargetFramework>
     <IsPackable>false</IsPackable>

From 1b14bd0062ba419d143922c5aa5ff7dff7e22507 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 18 Feb 2018 10:37:07 -0600
Subject: [PATCH 089/227] fix tests

---
 src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index adc3883dd3..ae7f95917b 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -177,7 +177,7 @@ private object SetHasOneRelationship(object entity,
                 if (relationshipAttr == null)
                     throw new JsonApiException(400, $"{_jsonApiContext.RequestEntity.EntityName} does not contain a relationship '{relationshipName}'");
 
-                var data = (Dictionary<string, string>) relationshipData.ExposedData;
+                var data = (Dictionary<string, object>) relationshipData.ExposedData;
 
                 if (data == null) return entity;
 

From 4c97c19d9f3a6561bab418740fa7d6c03623cdfb Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 18 Feb 2018 16:55:49 -0600
Subject: [PATCH 090/227] feat(operations): remove JSON pointers from previous
 spec draft

---
 .../IServiceCollectionExtensions.cs           |  3 -
 .../JsonApiOperationsInputFormatter.cs        | 35 -----------
 .../DocumentDataPointerReplacement.cs         | 59 -------------------
 .../Operations/OperationsProcessor.cs         | 20 +------
 .../ResourceRefPointerReplacement.cs          | 34 -----------
 .../WebHostCollection.cs                      | 13 ++--
 6 files changed, 7 insertions(+), 157 deletions(-)
 delete mode 100644 src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
 delete mode 100644 src/JsonApiDotNetCore/Services/Operations/DocumentDataPointerReplacement.cs
 delete mode 100644 src/JsonApiDotNetCore/Services/Operations/ResourceRefPointerReplacement.cs

diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index cd068ead6a..437132f087 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -163,9 +163,6 @@ public static void SerializeAsJsonApi(this MvcOptions options, JsonApiOptions js
         {
             options.InputFormatters.Insert(0, new JsonApiInputFormatter());
 
-            if (jsonApiOptions.EnabledExtensions.Contains(JsonApiExtension.Operations))
-                options.InputFormatters.Insert(0, new JsonApiOperationsInputFormatter());
-
             options.OutputFormatters.Insert(0, new JsonApiOutputFormatter());
 
             options.Conventions.Insert(0, new DasherizedRoutingConvention(jsonApiOptions.Namespace));
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
deleted file mode 100644
index 6f114aff33..0000000000
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsInputFormatter.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc.Formatters;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Primitives;
-
-namespace JsonApiDotNetCore.Formatters
-{
-    public class JsonApiOperationsInputFormatter : IInputFormatter
-    {
-        internal const string PROFILE_EXTENSION = "<http://example.org/profiles/myjsonstuff>; rel=\"profile\"";
-
-        public bool CanRead(InputFormatterContext context)
-        {
-            if (context == null)
-                throw new ArgumentNullException(nameof(context));
-
-            var contentTypeString = context.HttpContext.Request.ContentType;
-
-            var canRead = (
-                contentTypeString == "application/vnd.api+json" &&
-                context.HttpContext.Request.Headers.TryGetValue("Link", out StringValues profileExtension) &&
-                profileExtension == PROFILE_EXTENSION
-            );
-
-            return canRead;
-        }
-
-        public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
-        {
-            var reader = context.HttpContext.RequestServices.GetService<IJsonApiOperationsReader>();
-            return await reader.ReadAsync(context);
-        }
-    }
-}
diff --git a/src/JsonApiDotNetCore/Services/Operations/DocumentDataPointerReplacement.cs b/src/JsonApiDotNetCore/Services/Operations/DocumentDataPointerReplacement.cs
deleted file mode 100644
index 7301353c3e..0000000000
--- a/src/JsonApiDotNetCore/Services/Operations/DocumentDataPointerReplacement.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System.Collections.Generic;
-using JsonApiDotNetCore.Models.Pointers;
-using Newtonsoft.Json.Linq;
-using JsonApiDotNetCore.Models;
-using JsonApiDotNetCore.Extensions;
-
-namespace JsonApiDotNetCore.Services.Operations
-{
-    public class DocumentDataPointerReplacement<TPointer, TPointerBase>
-        where TPointer : Pointer<TPointerBase>, new()
-    {
-        private readonly DocumentData _data;
-
-        public DocumentDataPointerReplacement(DocumentData data)
-        {
-            _data = data;
-        }
-
-        public void ReplacePointers(List<TPointerBase> parentDoc)
-        {
-            _data.Id = GetPointerValue(_data.Id, parentDoc);
-            _data.Type = GetPointerValue(_data.Type, parentDoc);
-
-            if (_data.Relationships != null)
-            {
-                foreach (var relationshipDictionary in _data.Relationships)
-                {
-                    if (relationshipDictionary.Value.IsHasMany)
-                    {
-                        foreach (var relationship in relationshipDictionary.Value.ManyData)
-                            ReplaceDictionaryPointers(relationship, parentDoc);
-                    }
-                    else
-                    {
-                        ReplaceDictionaryPointers(relationshipDictionary.Value.SingleData, parentDoc);
-                    }
-                }
-            }
-        }
-
-        private void ReplaceDictionaryPointers(Dictionary<string, object> relationship, List<TPointerBase> parentDoc)
-        {
-            if (relationship.ContainsKey("id"))
-                relationship["id"] = GetPointerValue(relationship["id"], parentDoc);
-
-            if (relationship.ContainsKey("type"))
-                relationship["type"] = GetPointerValue(relationship["type"], parentDoc);
-        }
-
-        private object GetPointerValue(object reference, List<TPointerBase> parentDoc)
-        {
-            if (reference is JObject jObj)
-                if (jObj.TryParse<TPointer, TPointerBase>(Pointer<TPointerBase>.JsonSchema, out Pointer<TPointerBase> pointer))
-                    return pointer.GetValue(parentDoc);
-
-            return reference;
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index 2873d243b1..e49e758570 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -61,8 +61,8 @@ private async Task ProcessOperation(Operation op, List<Operation> outputOps)
         {
             var operationsPointer = new OperationsPointer();
 
-            ReplaceDataPointers(op.DataObject, outputOps);
-            ReplaceRefPointers(op.Ref, outputOps);
+            // ReplaceDataPointers(op.DataObject, outputOps);
+            // ReplaceRefPointers(op.Ref, outputOps);
 
             var processor = GetOperationsProcessor(op);
             var resultOp = await processor.ProcessAsync(op);
@@ -71,22 +71,6 @@ private async Task ProcessOperation(Operation op, List<Operation> outputOps)
                 outputOps.Add(resultOp);
         }
 
-        private void ReplaceDataPointers(DocumentData dataObject, List<Operation> outputOps)
-        {
-            if (dataObject == null) return;
-
-            var replacer = new DocumentDataPointerReplacement<OperationsPointer, Operation>(dataObject);
-            replacer.ReplacePointers(outputOps);
-        }
-
-        private void ReplaceRefPointers(ResourceReference resourceRef, List<Operation> outputOps)
-        {
-            if (resourceRef == null) return;
-
-            var replacer = new ResourceRefPointerReplacement<OperationsPointer, Operation>(resourceRef);
-            replacer.ReplacePointers(outputOps);
-        }
-
         private IOpProcessor GetOperationsProcessor(Operation op)
         {
             switch (op.Op)
diff --git a/src/JsonApiDotNetCore/Services/Operations/ResourceRefPointerReplacement.cs b/src/JsonApiDotNetCore/Services/Operations/ResourceRefPointerReplacement.cs
deleted file mode 100644
index d24d7e879a..0000000000
--- a/src/JsonApiDotNetCore/Services/Operations/ResourceRefPointerReplacement.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.Collections.Generic;
-using JsonApiDotNetCore.Models.Pointers;
-using Newtonsoft.Json.Linq;
-using JsonApiDotNetCore.Extensions;
-using JsonApiDotNetCore.Models.Operations;
-
-namespace JsonApiDotNetCore.Services.Operations
-{
-    public class ResourceRefPointerReplacement<TPointer, TPointerBase>
-        where TPointer : Pointer<TPointerBase>, new()
-    {
-        private readonly ResourceReference _ref;
-
-        public ResourceRefPointerReplacement(ResourceReference data)
-        {
-            _ref = data;
-        }
-
-        public void ReplacePointers(List<TPointerBase> parentDoc)
-        {
-            _ref.Id = GetPointerValue(_ref.Id, parentDoc);
-            _ref.Type = GetPointerValue(_ref.Type, parentDoc);
-        }
-
-        private object GetPointerValue(object reference, List<TPointerBase> parentDoc)
-        {
-            if (reference is JObject jObj)
-                if (jObj.TryParse<TPointer, TPointerBase>(Pointer<TPointerBase>.JsonSchema, out Pointer<TPointerBase> pointer))
-                    return pointer.GetValue(parentDoc);
-
-            return reference;
-        }
-    }
-}
\ No newline at end of file
diff --git a/test/OperationsExampleTests/WebHostCollection.cs b/test/OperationsExampleTests/WebHostCollection.cs
index dc4f02a58c..e385ace992 100644
--- a/test/OperationsExampleTests/WebHostCollection.cs
+++ b/test/OperationsExampleTests/WebHostCollection.cs
@@ -1,13 +1,11 @@
-using System;
 using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
 using Microsoft.AspNetCore.Hosting;
-using OperationsExample;
-using Xunit;
 using Microsoft.AspNetCore.TestHost;
 using Newtonsoft.Json;
-using System.Net.Http.Headers;
-using System.Threading.Tasks;
-using JsonApiDotNetCore.Formatters;
+using OperationsExample;
+using Xunit;
 
 namespace OperationsExampleTests
 {
@@ -35,7 +33,6 @@ public async Task<HttpResponseMessage> PatchAsync(string route, object data)
             request.Content = new StringContent(JsonConvert.SerializeObject(data));
             request.Content.Headers.ContentLength = 1;
             request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
-            request.Content.Headers.Add("Link", JsonApiOperationsInputFormatter.PROFILE_EXTENSION);
             return await Client.SendAsync(request);
         }
 
@@ -47,4 +44,4 @@ public async Task<HttpResponseMessage> PatchAsync(string route, object data)
             return (response, obj);
         }
     }
-}
\ No newline at end of file
+}

From 6b50baf72ecd49e18440196d9e3abbc19502f6e9 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 18 Feb 2018 16:57:25 -0600
Subject: [PATCH 091/227] breaking(Document): introduce RO and RIO from spec

DocumentData becomes ResourceObject
and dictionary in Relationship becomes strongly type ResourceIdentifierObject
---
 .../Builders/DocumentBuilder.cs               | 20 +++++-----
 src/JsonApiDotNetCore/Models/DocumentData.cs  | 21 ++--------
 .../Models/RelationshipData.cs                | 15 ++++----
 .../Models/ResourceIdentifierObject.cs        | 16 ++++++++
 .../Models/ResourceObject.cs                  | 14 +++++++
 .../Serialization/JsonApiDeSerializer.cs      |  4 +-
 .../UnitTests/Models/RelationshipDataTests.cs | 38 +++++++++++--------
 .../Operations/OperationsProcessorTests.cs    |  2 +-
 8 files changed, 77 insertions(+), 53 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Models/ResourceIdentifierObject.cs
 create mode 100644 src/JsonApiDotNetCore/Models/ResourceObject.cs

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 95227abd58..0e43225b35 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -234,32 +234,32 @@ private bool RelationshipIsIncluded(string relationshipName)
                 _jsonApiContext.IncludedRelationships.Contains(relationshipName);
         }
 
-        private List<Dictionary<string, object>> GetRelationships(IEnumerable<object> entities)
+        private List<ResourceIdentifierObject> GetRelationships(IEnumerable<object> entities)
         {
             var objType = entities.GetElementType();
 
             var typeName = _jsonApiContext.ContextGraph.GetContextEntity(objType);
 
-            var relationships = new List<Dictionary<string, object>>();
+            var relationships = new List<ResourceIdentifierObject>();
             foreach (var entity in entities)
             {
-                relationships.Add(new Dictionary<string, object> {
-                    {"type", typeName.EntityName },
-                    {"id", ((IIdentifiable)entity).StringId }
+                relationships.Add(new ResourceIdentifierObject {
+                    Type = typeName.EntityName,
+                    Id = ((IIdentifiable)entity).StringId
                 });
             }
             return relationships;
         }
-        private Dictionary<string, object> GetRelationship(object entity)
+        private ResourceIdentifierObject GetRelationship(object entity)
         {
             var objType = entity.GetType();
 
             var typeName = _jsonApiContext.ContextGraph.GetContextEntity(objType);
 
-            return new Dictionary<string, object> {
-                    {"type", typeName.EntityName },
-                    {"id", ((IIdentifiable)entity).StringId }
-                };
+            return new ResourceIdentifierObject {
+                Type = typeName.EntityName,
+                Id = ((IIdentifiable)entity).StringId
+            };
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/DocumentData.cs b/src/JsonApiDotNetCore/Models/DocumentData.cs
index 7b5bdadd5b..ba1ce646c0 100644
--- a/src/JsonApiDotNetCore/Models/DocumentData.cs
+++ b/src/JsonApiDotNetCore/Models/DocumentData.cs
@@ -1,20 +1,5 @@
-using System.Collections.Generic;
-using Newtonsoft.Json;
-
 namespace JsonApiDotNetCore.Models
 {
-    public class DocumentData
-    {
-        [JsonProperty("type")]
-        public object Type { get; set; }
-
-        [JsonProperty("id")]
-        public object Id { get; set; }
-
-        [JsonProperty("attributes")]
-        public Dictionary<string, object> Attributes { get; set; }
-
-        [JsonProperty("relationships", NullValueHandling = NullValueHandling.Ignore)]
-        public Dictionary<string, RelationshipData> Relationships { get; set; }
-    }
-}
\ No newline at end of file
+    // TODO: deprecate DocumentData in favor of ResourceObject
+    public class DocumentData : ResourceObject { }
+}
diff --git a/src/JsonApiDotNetCore/Models/RelationshipData.cs b/src/JsonApiDotNetCore/Models/RelationshipData.cs
index d81b2fe75a..1cfe47c5c7 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipData.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipData.cs
@@ -1,4 +1,3 @@
-using System.Collections;
 using System.Collections.Generic;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
@@ -22,9 +21,9 @@ public object ExposedData
             set
             {
                 if (value is JObject jObject)
-                    SingleData = jObject.ToObject<Dictionary<string, object>>();
-                else if (value is Dictionary<string, object> dict)
-                    SingleData = (Dictionary<string, object>)value;
+                    SingleData = jObject.ToObject<ResourceIdentifierObject>();
+                else if (value is ResourceIdentifierObject dict)
+                    SingleData = (ResourceIdentifierObject)value;
                 else
                     SetManyData(value);
             }
@@ -34,16 +33,16 @@ private void SetManyData(object value)
         {
             IsHasMany = true;
             if (value is JArray jArray)
-                ManyData = jArray.ToObject<List<Dictionary<string, object>>>();
+                ManyData = jArray.ToObject<List<ResourceIdentifierObject>>();
             else
-                ManyData = (List<Dictionary<string, object>>)value;
+                ManyData = (List<ResourceIdentifierObject>)value;
         }
 
         [JsonIgnore]
-        public List<Dictionary<string, object>> ManyData { get; set; }
+        public List<ResourceIdentifierObject> ManyData { get; set; }
 
         [JsonIgnore]
-        public Dictionary<string, object> SingleData { get; set; }
+        public ResourceIdentifierObject SingleData { get; set; }
 
         [JsonIgnore]
         public bool IsHasMany { get; private set; }
diff --git a/src/JsonApiDotNetCore/Models/ResourceIdentifierObject.cs b/src/JsonApiDotNetCore/Models/ResourceIdentifierObject.cs
new file mode 100644
index 0000000000..1ebab6c474
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/ResourceIdentifierObject.cs
@@ -0,0 +1,16 @@
+using Newtonsoft.Json;
+
+namespace JsonApiDotNetCore.Models
+{
+    public class ResourceIdentifierObject
+    {
+        [JsonProperty("type")]
+        public string Type { get; set; }
+        
+        [JsonProperty("id")]
+        public string Id { get; set; }
+
+        [JsonProperty("lid")]
+        public string LocalId { get; set; }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Models/ResourceObject.cs b/src/JsonApiDotNetCore/Models/ResourceObject.cs
new file mode 100644
index 0000000000..1a28631407
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/ResourceObject.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace JsonApiDotNetCore.Models
+{
+    public class ResourceObject : ResourceIdentifierObject
+    {
+        [JsonProperty("attributes")]
+        public Dictionary<string, object> Attributes { get; set; }
+
+        [JsonProperty("relationships", NullValueHandling = NullValueHandling.Ignore)]
+        public Dictionary<string, RelationshipData> Relationships { get; set; }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index ae7f95917b..1765687c0a 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -218,7 +218,9 @@ private object SetHasManyRelationship(object entity,
                 if (data == null) return entity;
 
                 var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(typeof(GenericProcessor<>), attr.Type);
-                var ids = relationshipData.ManyData.Select(r => r["id"].ToString());
+
+                var ids = relationshipData.ManyData.Select(r => r.Id);
+
                 genericProcessor.SetRelationships(entity, attr, ids);
             }
 
diff --git a/test/UnitTests/Models/RelationshipDataTests.cs b/test/UnitTests/Models/RelationshipDataTests.cs
index 780a5faa0b..ff00144b62 100644
--- a/test/UnitTests/Models/RelationshipDataTests.cs
+++ b/test/UnitTests/Models/RelationshipDataTests.cs
@@ -1,7 +1,7 @@
-using JsonApiDotNetCore.Models;
-using System.Collections.Generic;
-using Xunit;
+using System.Collections.Generic;
+using JsonApiDotNetCore.Models;
 using Newtonsoft.Json.Linq;
+using Xunit;
 
 namespace UnitTests.Models
 {
@@ -12,9 +12,10 @@ public void Setting_ExposedData_To_List_Sets_ManyData()
         {
             // arrange
             var relationshipData = new RelationshipData();
-            var relationships = new List<Dictionary<string, object>> {
-                new Dictionary<string, object> {
-                    { "authors", new { } }
+            var relationships = new List<ResourceIdentifierObject> {
+                new ResourceIdentifierObject {
+                    Id = "9",
+                    Type = "authors"
                 }
             };
 
@@ -23,7 +24,8 @@ public void Setting_ExposedData_To_List_Sets_ManyData()
 
             // assert
             Assert.NotEmpty(relationshipData.ManyData);
-            Assert.True(relationshipData.ManyData[0].ContainsKey("authors"));
+            Assert.Equal("authors", relationshipData.ManyData[0].Type);
+            Assert.Equal("9", relationshipData.ManyData[0].Id);
             Assert.True(relationshipData.IsHasMany);
         }
 
@@ -34,7 +36,8 @@ public void Setting_ExposedData_To_JArray_Sets_ManyData()
             var relationshipData = new RelationshipData();
             var relationshipsJson = @"[
                 {
-                    ""authors"": {}
+                    ""type"": ""authors"",
+                    ""id"": ""9""
                 }
             ]";
 
@@ -45,17 +48,19 @@ public void Setting_ExposedData_To_JArray_Sets_ManyData()
 
             // assert
             Assert.NotEmpty(relationshipData.ManyData);
-            Assert.True(relationshipData.ManyData[0].ContainsKey("authors"));
+            Assert.Equal("authors", relationshipData.ManyData[0].Type);
+            Assert.Equal("9", relationshipData.ManyData[0].Id);
             Assert.True(relationshipData.IsHasMany);
         }
 
         [Fact]
-        public void Setting_ExposedData_To_Dictionary_Sets_SingleData()
+        public void Setting_ExposedData_To_RIO_Sets_SingleData()
         {
             // arrange
             var relationshipData = new RelationshipData();
-            var relationship = new Dictionary<string, object> {
-                { "authors", new { } }
+            var relationship = new ResourceIdentifierObject {
+                Id = "9",
+                Type = "authors"
             };
 
             // act 
@@ -63,7 +68,8 @@ public void Setting_ExposedData_To_Dictionary_Sets_SingleData()
 
             // assert
             Assert.NotNull(relationshipData.SingleData);
-            Assert.True(relationshipData.SingleData.ContainsKey("authors"));
+            Assert.Equal("authors", relationshipData.SingleData.Type);
+            Assert.Equal("9", relationshipData.SingleData.Id);
             Assert.False(relationshipData.IsHasMany);
         }
 
@@ -73,7 +79,8 @@ public void Setting_ExposedData_To_JObject_Sets_SingleData()
             // arrange
             var relationshipData = new RelationshipData();
             var relationshipJson = @"{
-                    ""authors"": {}
+                    ""id"": ""9"",
+                    ""type"": ""authors""
                 }";
 
             var relationship = JObject.Parse(relationshipJson);
@@ -83,7 +90,8 @@ public void Setting_ExposedData_To_JObject_Sets_SingleData()
 
             // assert
             Assert.NotNull(relationshipData.SingleData);
-            Assert.True(relationshipData.SingleData.ContainsKey("authors"));
+            Assert.Equal("authors", relationshipData.SingleData.Type);
+            Assert.Equal("9", relationshipData.SingleData.Id);
             Assert.False(relationshipData.IsHasMany);
         }
     }
diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
index 74298f0cca..fb098d3f78 100644
--- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -98,7 +98,7 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
                 m => m.ProcessAsync(
                     It.Is<Operation>(o =>
                         o.DataObject.Type.ToString() == "articles"
-                        && o.DataObject.Relationships["author"].SingleData["id"].ToString() == "9"
+                        && o.DataObject.Relationships["author"].SingleData.Id == "9"
                     )
                 )
             );

From f3cb9d98659a48f5175a3d1517d5a9580445ecdd Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 18 Feb 2018 17:26:09 -0600
Subject: [PATCH 092/227] fix standad tests

---
 .../Serialization/JsonApiDeSerializer.cs      |     8 +-
 test/JsonApiDotNetCoreExampleTests/results    | 19364 ++++++++++++++++
 .../Serialization/JsonApiSerializerTests.cs   |     8 +-
 3 files changed, 19370 insertions(+), 10 deletions(-)
 create mode 100644 test/JsonApiDotNetCoreExampleTests/results

diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 1765687c0a..ef7938dbd3 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -177,11 +177,11 @@ private object SetHasOneRelationship(object entity,
                 if (relationshipAttr == null)
                     throw new JsonApiException(400, $"{_jsonApiContext.RequestEntity.EntityName} does not contain a relationship '{relationshipName}'");
 
-                var data = (Dictionary<string, object>) relationshipData.ExposedData;
+                var rio = (ResourceIdentifierObject) relationshipData.ExposedData;
 
-                if (data == null) return entity;
+                if (rio == null) return entity;
 
-                var newValue = data["id"];
+                var newValue = rio.Id;
 
                 var foreignKey = attr.InternalRelationshipName + "Id";
                 var entityProperty = entityProperties.FirstOrDefault(p => p.Name == foreignKey);
@@ -213,7 +213,7 @@ private object SetHasManyRelationship(object entity,
 
             if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
             {
-                var data = (List<Dictionary<string, object>>)relationshipData.ExposedData;
+                var data = (List<ResourceIdentifierObject>)relationshipData.ExposedData;
 
                 if (data == null) return entity;
 
diff --git a/test/JsonApiDotNetCoreExampleTests/results b/test/JsonApiDotNetCoreExampleTests/results
new file mode 100644
index 0000000000..09e896913c
--- /dev/null
+++ b/test/JsonApiDotNetCoreExampleTests/results
@@ -0,0 +1,19364 @@
+Build started, please wait...
+Build completed.
+
+Test run for /Users/jarednance/dev/json-api-dotnet-core/test/JsonApiDotNetCoreExampleTests/bin/Debug/netcoreapp2.0/JsonApiDotNetCoreExampleTests.dll(.NETCoreApp,Version=v2.0)
+Microsoft (R) Test Execution Command Line Tool Version 15.3.0-preview-20170628-02
+Copyright (c) Microsoft Corporation.  All rights reserved.
+
+Starting test execution, please wait...
+[xUnit.net 00:00:01.5429620]   Discovering: JsonApiDotNetCoreExampleTests
+[xUnit.net 00:00:01.7795750]   Discovered:  JsonApiDotNetCoreExampleTests
+[xUnit.net 00:00:01.9136060]   Starting:    JsonApiDotNetCoreExampleTests
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (46ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (21ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (21ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/camelCasedModels  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/camelCasedModels  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'CamelCasedModels'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PostAsync (JsonApiDotNetCoreExample)' with id 'c71c760f-c1d1-4899-8d4b-62a4348b63f7' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from CamelCasedModel <generated>_1 in DbSet<CamelCasedModel>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from CamelCasedModel <generated>_1 in DbSet<CamelCasedModel>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "CamelCasedModels" AS "c"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "CamelCasedModels" AS "c"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "CamelCasedModels" AS "c"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "CamelCasedModels" AS "c"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from CamelCasedModel <generated>_2 in DbSet<CamelCasedModel>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from CamelCasedModel <generated>_2 in DbSet<CamelCasedModel> select [<generated>_2]).Skip(__p_0).Ta...' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from CamelCasedModel <generated>_2 in DbSet<CamelCasedModel> select [<generated>_2]).Skip(__p_0).Ta...' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from CamelCasedModel <generated>_2 in DbSet<CamelCasedModel>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<CamelCasedModel> _InterceptExceptions(
+          source: IAsyncEnumerable<CamelCasedModel> _TrackEntities(
+              results: IAsyncEnumerable<CamelCasedModel> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "c"."Id", "c"."CompoundAttr"
+                      FROM "CamelCasedModels" AS "c"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<CamelCasedModel>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: CamelCasedModel }, 
+              entityAccessors: List<Func<CamelCasedModel, object>> 
+              { 
+                  Func<CamelCasedModel, CamelCasedModel>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "c"."Id", "c"."CompoundAttr"
+      FROM "CamelCasedModels" AS "c"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (17ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "c"."Id", "c"."CompoundAttr"
+      FROM "CamelCasedModels" AS "c"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (17ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "c"."Id", "c"."CompoundAttr"
+      FROM "CamelCasedModels" AS "c"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample) in 797.042ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample) in 797.042ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 1177.077ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 1177.077ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/camelCasedModels/118 application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/camelCasedModels/118 application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'CamelCasedModels/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample)' with id '56304397-4d3c-4262-91df-9d2020a11d38' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.DeleteAsync (JsonApiDotNetCoreExample)' with id 'b4ae66ce-aa8f-4c8e-869c-4b784d8bff92' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PatchAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (118, JsonApiDotNetCoreExample.Models.CamelCasedModel) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (118, JsonApiDotNetCoreExample.Models.CamelCasedModel) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from CamelCasedModel e in DbSet<CamelCasedModel>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from CamelCasedModel e in DbSet<CamelCasedModel>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<CamelCasedModel> _InterceptExceptions(
+          source: IAsyncEnumerable<CamelCasedModel> _TrackEntities(
+              results: IAsyncEnumerable<CamelCasedModel> _ToSequence(Task<CamelCasedModel> SingleOrDefault(
+                      source: IAsyncEnumerable<CamelCasedModel> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."CompoundAttr"
+                              FROM "CamelCasedModels" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<CamelCasedModel>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: CamelCasedModel }, 
+              entityAccessors: List<Func<CamelCasedModel, object>> 
+              { 
+                  Func<CamelCasedModel, CamelCasedModel>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."CompoundAttr"
+      FROM "CamelCasedModels" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."CompoundAttr"
+      FROM "CamelCasedModels" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."CompoundAttr"
+      FROM "CamelCasedModels" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "CamelCasedModels" SET "CompoundAttr" = @p0
+      WHERE "Id" = @p1;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "CamelCasedModels" SET "CompoundAttr" = @p0
+      WHERE "Id" = @p1;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "CamelCasedModels" SET "CompoundAttr" = @p0
+      WHERE "Id" = @p1;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PatchAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PatchAsync (JsonApiDotNetCoreExample) in 354.058ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PatchAsync (JsonApiDotNetCoreExample) in 354.058ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 419.972ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 419.972ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/camelCasedModels application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/camelCasedModels application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'CamelCasedModels'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample)' with id '666fde0d-b734-495f-ad63-c5150103bbae' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PostAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.CamelCasedModel) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.CamelCasedModel) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PostAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.CreatedResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PostAsync (JsonApiDotNetCoreExample) in 53.052ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 68.79ms 201 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PostAsync (JsonApiDotNetCoreExample) in 53.052ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 68.79ms 201 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "CamelCasedModels" ("CompoundAttr")
+      VALUES (@p0)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/camelCasedModels/120  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/camelCasedModels/120  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'CamelCasedModels/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.PatchAsync (JsonApiDotNetCoreExample)' with id 'e8c838e7-928c-4438-9423-73d694f2a735' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.DeleteAsync (JsonApiDotNetCoreExample)' with id 'd3dc7c59-c458-484c-864d-c679f2275710' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample) with arguments (120) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample) with arguments (120) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from CamelCasedModel e in DbSet<CamelCasedModel>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from CamelCasedModel e in DbSet<CamelCasedModel>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<CamelCasedModel> _InterceptExceptions(
+          source: IAsyncEnumerable<CamelCasedModel> _TrackEntities(
+              results: IAsyncEnumerable<CamelCasedModel> _ToSequence(Task<CamelCasedModel> SingleOrDefault(
+                      source: IAsyncEnumerable<CamelCasedModel> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."CompoundAttr"
+                              FROM "CamelCasedModels" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<CamelCasedModel>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: CamelCasedModel }, 
+              entityAccessors: List<Func<CamelCasedModel, object>> 
+              { 
+                  Func<CamelCasedModel, CamelCasedModel>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."CompoundAttr"
+      FROM "CamelCasedModels" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (13ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."CompoundAttr"
+      FROM "CamelCasedModels" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (13ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."CompoundAttr"
+      FROM "CamelCasedModels" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample) in 54.591ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 73.364ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.CamelCasedModelsController.GetAsync (JsonApiDotNetCoreExample) in 54.591ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 73.364ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/readonly  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/readonly  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'ReadOnly'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample)' with id '9ceae986-2052-4187-bc60-6db234b1ede5' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Post (JsonApiDotNetCoreExample)' with id '4de72652-5656-423c-b4be-3cd9c940d171' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Delete (JsonApiDotNetCoreExample)' with id '521d748c-b696-4748-b738-371680d2c9e3' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Patch (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support PATCH requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support PATCH requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Patch (JsonApiDotNetCoreExample) in 25.699ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Patch (JsonApiDotNetCoreExample) in 25.699ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 41.952ms 405 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 41.952ms 405 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/readonly  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/readonly  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'ReadOnly'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample)' with id '18714b6d-0833-4259-935e-8efa022d086d' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Post (JsonApiDotNetCoreExample)' with id '0fef2165-3efb-4658-933a-7ae6ef0c7232' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Patch (JsonApiDotNetCoreExample)' with id '1d6daeba-8dfb-4b24-b56b-7a5283a29bc4' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Delete (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support DELETE requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support DELETE requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Delete (JsonApiDotNetCoreExample) in 6.393ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Delete (JsonApiDotNetCoreExample) in 6.393ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.237ms 405 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.237ms 405 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/readonly  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/readonly  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'ReadOnly'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample)' with id '6a344e07-367a-4086-a290-a9ac9ff653b2' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Patch (JsonApiDotNetCoreExample)' with id '65f4bfd4-7222-41ed-8406-d267a25771cc' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Delete (JsonApiDotNetCoreExample)' with id '7151bfbd-129b-4a37-a514-c5cb1561f85c' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Post (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support POST requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support POST requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Post (JsonApiDotNetCoreExample) in 3.628ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Post (JsonApiDotNetCoreExample) in 3.628ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.455ms 405 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.455ms 405 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/readonly  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/readonly  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'ReadOnly'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Post (JsonApiDotNetCoreExample)' with id 'd692e0ba-f723-4660-aeb5-bb2fab767d08' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Patch (JsonApiDotNetCoreExample)' with id 'bb9f84b7-1768-4c5c-a5d4-8142f3aa7da2' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Delete (JsonApiDotNetCoreExample)' with id 'cadd349f-7374-4fc1-97df-b7df9a994684' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample) in 3.6ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.ReadOnlyController.Get (JsonApiDotNetCoreExample) in 3.6ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.744ms 200 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.744ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/nohttpdelete  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/nohttpdelete  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpDelete'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample)' with id 'e8ba1352-03b1-4166-9e79-1ce0c48f95f7' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample)' with id 'ebe48f67-b775-4198-b4d8-dae0bbabc2e6' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Delete (JsonApiDotNetCoreExample)' with id '01ed4864-4f42-4865-af7f-c39b40fea67b' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample) in 0.719ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 14.875ms 200 
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample) in 0.719ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 14.875ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/nohttpdelete  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/nohttpdelete  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpDelete'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample)' with id '72b19a09-1b1f-4691-a363-cb0f10df7f44' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample)' with id '37d45424-cba6-4b3a-b19c-66490c70208f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample)' with id '6dd43591-857d-4625-8fa4-a261d04da16b' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Delete (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support DELETE requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support DELETE requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Delete (JsonApiDotNetCoreExample) in 3.513ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Delete (JsonApiDotNetCoreExample) in 3.513ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.684ms 405 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.684ms 405 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/nohttpdelete  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/nohttpdelete  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpDelete'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample)' with id 'c95f1a88-8eff-4b37-8f6a-7d8b7398b131' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample)' with id '9ea775d5-e54f-4b2c-b274-e2d8010d4134' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Delete (JsonApiDotNetCoreExample)' with id 'f9ede477-a111-42f0-a8bf-5b81166908ee' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample) in 0.329ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 15.698ms 200 
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample) in 0.329ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 15.698ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/nohttpdelete  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/nohttpdelete  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpDelete'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Get (JsonApiDotNetCoreExample)' with id 'c702b174-b075-49f0-a851-626c2f1dceac' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Post (JsonApiDotNetCoreExample)' with id 'a34519c4-5ff5-47fa-a55e-fdcddd23ac7d' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Delete (JsonApiDotNetCoreExample)' with id '1cdfd359-36bc-421e-a025-7af36c463692' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample) in 0.378ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.973ms 200 
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpDeleteController.Patch (JsonApiDotNetCoreExample) in 0.378ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.973ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/nohttppatch  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/nohttppatch  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpPatch'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample)' with id '0a47ec59-9bd6-4f86-8ae7-784146f24d25' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample)' with id 'c40826a8-bb78-495b-a580-8a34f21f90e1' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Patch (JsonApiDotNetCoreExample)' with id '65968202-d190-4c70-9ac5-855e064ec85c' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample) in 0.544ms
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.402ms 200 
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample) in 0.544ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.402ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/nohttppatch  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/nohttppatch  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpPatch'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample)' with id '9b16d4b3-796c-4630-b944-4a0c28230844' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample)' with id '867fa153-19b0-422e-aa0a-30a3f58f84e0' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample)' with id '82d36401-dc08-4ff0-b285-dd2f8d333f59' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Patch (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support PATCH requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support PATCH requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Patch (JsonApiDotNetCoreExample) in 7.468ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Patch (JsonApiDotNetCoreExample) in 7.468ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 19.429ms 405 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 19.429ms 405 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/nohttppatch  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/nohttppatch  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpPatch'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample)' with id '957f4e51-8d40-4405-a523-0f3096cf96c1' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Patch (JsonApiDotNetCoreExample)' with id 'a69c8f75-6924-4fcf-b2b3-c5d0277d4340' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample)' with id '74dbbd63-6ca3-4fbd-8077-3b4f30a6f6e0' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample) in 0.608ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample) in 0.608ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 20.436ms 200 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 20.436ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/nohttppatch  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/nohttppatch  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpPatch'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Get (JsonApiDotNetCoreExample)' with id 'e9ebb853-6169-4cc6-ba17-54a9ed00e805' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Patch (JsonApiDotNetCoreExample)' with id 'dab9b84a-0944-4807-bcbc-6dc1e7964c47' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Delete (JsonApiDotNetCoreExample)' with id '7e09310e-ec5e-4829-be57-632f6f7d1c89' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample) in 0.452ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 14.392ms 200 
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPatchController.Post (JsonApiDotNetCoreExample) in 0.452ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 14.392ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/nohttppost  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/nohttppost  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpPost'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample)' with id '2c61d7ce-c38b-43b3-b51b-702e595f6b37' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Post (JsonApiDotNetCoreExample)' with id 'fded13c7-20e9-402b-9cd0-66aee2c5fee4' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample)' with id '28252322-bbf4-46b2-8941-284cc1b1df1a' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample) in 0.934ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample) in 0.934ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.025ms 200 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.025ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/nohttppost  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/nohttppost  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpPost'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Post (JsonApiDotNetCoreExample)' with id 'eab96b94-f493-457f-97de-9b2995d5557a' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample)' with id '38baef8d-7d72-46dd-9f2a-bd1de31f9e15' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample)' with id '5e424bdc-48fd-4059-b3df-2f40347c6fac' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample) in 0.346ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.34ms 200 
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample) in 0.346ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.34ms 200 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/nohttppost  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/nohttppost  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpPost'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample)' with id 'aa8ab36f-b617-4d80-8754-7342c289a15b' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample)' with id '71ab4fa0-892e-4cfa-bec8-6d1fa27fdc09' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample)' with id '2a0fc13f-0311-4ed2-a6fe-33f0355d1962' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Post (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support POST requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: This resource does not support POST requests.
+   at JsonApiDotNetCore.Controllers.HttpRestrictAttribute.<OnActionExecutionAsync>d__2.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/HttpMethodRestrictionFilter.cs:line 21
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Post (JsonApiDotNetCoreExample) in 3.885ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Post (JsonApiDotNetCoreExample) in 3.885ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 19.512ms 405 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 19.512ms 405 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/nohttppost  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/nohttppost  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'NoHttpPost'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Get (JsonApiDotNetCoreExample)' with id 'e8d78aa6-b1bc-490e-b743-11e7d5769b09' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Post (JsonApiDotNetCoreExample)' with id '2d2b399d-9677-4946-bf9a-f0c8c4e644c3' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Patch (JsonApiDotNetCoreExample)' with id '9d2d6081-3838-4c95-9310-84cfce59572d' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample) in 0.446ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.61ms 200 
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.Restricted.NoHttpPostController.Delete (JsonApiDotNetCoreExample) in 0.446ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 18.61ms 200 
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      'from TodoItem <generated>_0 in DbSet<TodoItem>
+      select [<generated>_0]'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      'from TodoItem <generated>_0 in DbSet<TodoItem>
+      select [<generated>_0]'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _TrackEntities(
+              results: IEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t", 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p15;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p16;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p17;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p18;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p19;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p20;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p21;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p28;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p29;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p30;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p31;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p32;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p33;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p34;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p15;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p16;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p17;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p18;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p19;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p20;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p21;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p28;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p29;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p30;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p31;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p32;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p33;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p34;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p15;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p16;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p17;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p18;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p19;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p20;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p21;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p28;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p29;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p30;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p31;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p32;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p33;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p34;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p35, @p36, @p37, @p38, @p39, @p40, @p41, @p42)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p43, @p44, @p45, @p46, @p47, @p48, @p49, @p50)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p51, @p52, @p53, @p54, @p55, @p56, @p57, @p58)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p59, @p60, @p61, @p62, @p63, @p64, @p65, @p66)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (18ms) [Parameters=[@p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p35, @p36, @p37, @p38, @p39, @p40, @p41, @p42)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p43, @p44, @p45, @p46, @p47, @p48, @p49, @p50)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p51, @p52, @p53, @p54, @p55, @p56, @p57, @p58)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p59, @p60, @p61, @p62, @p63, @p64, @p65, @p66)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (18ms) [Parameters=[@p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p35, @p36, @p37, @p38, @p39, @p40, @p41, @p42)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p43, @p44, @p45, @p46, @p47, @p48, @p49, @p50)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p51, @p52, @p53, @p54, @p55, @p56, @p57, @p58)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p59, @p60, @p61, @p62, @p63, @p64, @p65, @p66)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?sort=-ordinal  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?sort=-ordinal  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem x in DbSet<TodoItem>
+      order by [x].Ordinal desc
+      select [x]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem x in DbSet<TodoItem>
+      select [x]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "x"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "x"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "x"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "x"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem x in DbSet<TodoItem>
+      order by [x].Ordinal desc
+      select [x])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem x in DbSet<TodoItem>
+      order by [x].Ordinal desc
+      select [x])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+                      FROM "TodoItems" AS "x"
+                      ORDER BY "x"."Ordinal" DESC
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+      ORDER BY "x"."Ordinal" DESC
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+      ORDER BY "x"."Ordinal" DESC
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+      ORDER BY "x"."Ordinal" DESC
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 73.508ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 73.508ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 90.09ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 90.09ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?filter[ordinal]=999999  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?filter[ordinal]=999999  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].Ordinal == 999999
+      select [model]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].Ordinal == 999999
+      select [model]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "model"
+                          WHERE "model"."Ordinal" = 999999), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE "model"."Ordinal" = 999999
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE "model"."Ordinal" = 999999
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE "model"."Ordinal" = 999999
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].Ordinal == 999999
+      select [model])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem model in DbSet<TodoItem> where [model].Ordinal == 999999 select [model]).Skip(__p_0)....' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem model in DbSet<TodoItem> where [model].Ordinal == 999999 select [model]).Skip(__p_0)....' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].Ordinal == 999999
+      select [model])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+                      FROM "TodoItems" AS "model"
+                      WHERE "model"."Ordinal" = 999999
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE "model"."Ordinal" = 999999
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE "model"."Ordinal" = 999999
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE "model"."Ordinal" = 999999
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 48.005ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 50.255ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 48.005ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 50.255ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2594  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2594  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2594) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2594) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+                              FROM "TodoItems" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<TodoItem>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 17.158ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 17.158ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 21.735ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 21.735ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2595 application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2595 application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id '432a039f-d92f-4b06-93f6-76d9e6be26be' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2595, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2595, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "AchievedDate" = @p0, "CreatedDate" = @p1, "Description" = @p2
+      WHERE "Id" = @p3;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "AchievedDate" = @p0, "CreatedDate" = @p1, "Description" = @p2
+      WHERE "Id" = @p3;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "AchievedDate" = @p0, "CreatedDate" = @p1, "Description" = @p2
+      WHERE "Id" = @p3;
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 22.314ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 27.243ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 22.314ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 27.243ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 9.452ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 9.452ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 9.891ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 9.891ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id 'f11b0d8e-7eb6-44c7-b10f-29a156acd6ba' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.CreatedResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 11.535ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 11.535ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.578ms 201 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 16.578ms 201 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2598 application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2598 application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id '432a039f-d92f-4b06-93f6-76d9e6be26be' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2598, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2598, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "AchievedDate" = @p0, "CreatedDate" = @p1, "Description" = @p2
+      WHERE "Id" = @p3;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "AchievedDate" = @p0, "CreatedDate" = @p1, "Description" = @p2
+      WHERE "Id" = @p3;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "AchievedDate" = @p0, "CreatedDate" = @p1, "Description" = @p2
+      WHERE "Id" = @p3;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 8.845ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 8.845ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 9.112ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 9.112ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p28, @p29, @p30, @p31, @p32, @p33, @p34, @p35)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p36, @p37, @p38, @p39, @p40, @p41, @p42, @p43)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p28, @p29, @p30, @p31, @p32, @p33, @p34, @p35)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p36, @p37, @p38, @p39, @p40, @p41, @p42, @p43)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p28, @p29, @p30, @p31, @p32, @p33, @p34, @p35)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p36, @p37, @p38, @p39, @p40, @p41, @p42, @p43)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?sort=ordinal  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?sort=ordinal  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem x in DbSet<TodoItem>
+      order by [x].Ordinal asc
+      select [x]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem x in DbSet<TodoItem>
+      select [x]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "x"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "x"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "x"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "x"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem x in DbSet<TodoItem>
+      order by [x].Ordinal asc
+      select [x])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem x in DbSet<TodoItem>
+      order by [x].Ordinal asc
+      select [x])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+                      FROM "TodoItems" AS "x"
+                      ORDER BY "x"."Ordinal"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+      ORDER BY "x"."Ordinal"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+      ORDER BY "x"."Ordinal"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+      ORDER BY "x"."Ordinal"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 14.927ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 14.927ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 15.301ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 15.301ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2603 application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2603 application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id '432a039f-d92f-4b06-93f6-76d9e6be26be' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2603, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2603, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "CreatedDate" = @p0, "Description" = @p1, "Ordinal" = @p2
+      WHERE "Id" = @p3;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "CreatedDate" = @p0, "Description" = @p1, "Ordinal" = @p2
+      WHERE "Id" = @p3;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p3='?', @p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "CreatedDate" = @p0, "Description" = @p1, "Ordinal" = @p2
+      WHERE "Id" = @p3;
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 5.286ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 5.286ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 5.705ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 5.705ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/api/v1/todo-items/2604 application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/api/v1/todo-items/2604 application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id '432a039f-d92f-4b06-93f6-76d9e6be26be' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample) with arguments (2604) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample) with arguments (2604) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.NoContentResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 204
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 204
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample) in 20.385ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample) in 20.385ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 24.713ms 204 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 24.713ms 204 
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem t in DbSet<TodoItem>
+      where [t].Id == __todoItem_Id_0
+      select [t]).FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem t in DbSet<TodoItem>
+      where [t].Id == __todoItem_Id_0
+      select [t]).FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _TrackEntities(
+              results: IEnumerable<TodoItem> _ToSequence(TodoItem FirstOrDefault(IEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                              FROM "TodoItems" AS "t"
+                              WHERE "t"."Id" = @__todoItem_Id_0
+                              LIMIT 1, 
+                          shaper: UnbufferedEntityShaper<TodoItem>))), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2605?include=owner  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2605?include=owner  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2605) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2605) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e])
+      .Include("Owner")
+      .FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[e].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      join Person e.Owner in DbSet<Person>
+      on Property([e], "OwnerId") equals (Nullable<int>)Property([e.Owner], "Id") into e.Owner_group
+      from Person e.Owner in 
+          (from Person e.Owner_groupItem in [e.Owner_group]
+          select [e.Owner_groupItem]).DefaultIfEmpty()
+      where bool [e].Id.Equals((object)__id_0)
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ [e.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      )).FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> FirstOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _Select(
+                          source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+                                  FROM "TodoItems" AS "e"
+                                  LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+                                  WHERE "e"."Id" = @__id_0
+                                  LIMIT 1, 
+                              shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                          selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                              queryContext: queryContext, 
+                              entity: t1.Outer, 
+                              included: new object[]{ t1.Inner }, 
+                              fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: TodoItem)
+                                  return !(bool ReferenceEquals(included[0], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[0], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Owner, 
+                                          entity: entity, 
+                                          value: included[0])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.TodoItems, 
+                                          entity: included[0], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                              }
+                          )), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 225.239ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 225.49ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 225.239ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 225.49ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?filter[description]=like:ui%20eum%20quo%20sit%20fugiat  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?filter[description]=like:ui%20eum%20quo%20sit%20fugiat  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where bool [model].Description.Contains("ui eum quo sit fugiat")
+      select [model]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where bool [model].Description.Contains("ui eum quo sit fugiat")
+      select [model]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "model"
+                          WHERE STRPOS("model"."Description", 'ui eum quo sit fugiat') > 0), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE STRPOS("model"."Description", 'ui eum quo sit fugiat') > 0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE STRPOS("model"."Description", 'ui eum quo sit fugiat') > 0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE STRPOS("model"."Description", 'ui eum quo sit fugiat') > 0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where bool [model].Description.Contains("ui eum quo sit fugiat")
+      select [model])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem model in DbSet<TodoItem> where bool [model].Description.Contains("ui eum quo sit fugi...' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem model in DbSet<TodoItem> where bool [model].Description.Contains("ui eum quo sit fugi...' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where bool [model].Description.Contains("ui eum quo sit fugiat")
+      select [model])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+                      FROM "TodoItems" AS "model"
+                      WHERE STRPOS("model"."Description", 'ui eum quo sit fugiat') > 0
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE STRPOS("model"."Description", 'ui eum quo sit fugiat') > 0
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE STRPOS("model"."Description", 'ui eum quo sit fugiat') > 0
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE STRPOS("model"."Description", 'ui eum quo sit fugiat') > 0
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 21.347ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 21.347ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 22.376ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 22.376ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner&filter[owner.first-name]=Crawford  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner&filter[owner.first-name]=Crawford  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].Owner.FirstName == "Crawford"
+      select [model])
+      .Include("Owner")
+      .Count()'
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[model].Owner' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[model].Owner' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      join Person model.Owner in DbSet<Person>
+      on Property([model], "OwnerId") equals (Nullable<int>)Property([model.Owner], "Id") into model.Owner_group
+      from Person model.Owner in 
+          (from Person model.Owner_groupItem in [model.Owner_group]
+          select [model.Owner_groupItem]).DefaultIfEmpty()
+      where [model.Owner]?.FirstName == "Crawford"
+      select [model]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "model"
+                          LEFT JOIN "People" AS "model.Owner" ON "model"."OwnerId" = "model.Owner"."Id"
+                          WHERE "model.Owner"."FirstName" = 'Crawford'), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      LEFT JOIN "People" AS "model.Owner" ON "model"."OwnerId" = "model.Owner"."Id"
+      WHERE "model.Owner"."FirstName" = 'Crawford'
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      LEFT JOIN "People" AS "model.Owner" ON "model"."OwnerId" = "model.Owner"."Id"
+      WHERE "model.Owner"."FirstName" = 'Crawford'
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      LEFT JOIN "People" AS "model.Owner" ON "model"."OwnerId" = "model.Owner"."Id"
+      WHERE "model.Owner"."FirstName" = 'Crawford'
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].Owner.FirstName == "Crawford"
+      select [model])
+      .Include("Owner")
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem model in DbSet<TodoItem> where [model].Owner.FirstName == "Crawford" select [model])....' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem model in DbSet<TodoItem> where [model].Owner.FirstName == "Crawford" select [model])....' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[model].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      join Person model.Owner in DbSet<Person>
+      on Property([model], "OwnerId") equals (Nullable<int>)Property([model.Owner], "Id") into model.Owner_group
+      from Person model.Owner in 
+          (from Person model.Owner_groupItem in [model.Owner_group]
+          select [model.Owner_groupItem]).DefaultIfEmpty()
+      where [model.Owner]?.FirstName == "Crawford"
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [model], 
+          included: new object[]{ [model.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      ))
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _Select(
+                  source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId", "model.Owner"."Id", "model.Owner"."FirstName", "model.Owner"."LastName"
+                          FROM "TodoItems" AS "model"
+                          LEFT JOIN "People" AS "model.Owner" ON "model"."OwnerId" = "model.Owner"."Id"
+                          WHERE "model.Owner"."FirstName" = 'Crawford'
+                          LIMIT @__p_1 OFFSET @__p_0, 
+                      shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                  selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                      queryContext: queryContext, 
+                      entity: t1.Outer, 
+                      included: new object[]{ t1.Inner }, 
+                      fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                      {
+                          Void queryContext.QueryBuffer.StartTracking(
+                              entity: entity, 
+                              entityType: EntityType: TodoItem)
+                          return !(bool ReferenceEquals(included[0], null)) ? 
+                          {
+                              Void queryContext.QueryBuffer.StartTracking(
+                                  entity: included[0], 
+                                  entityType: EntityType: Person)
+                              Void SetRelationshipSnapshotValue(
+                                  stateManager: queryContext.StateManager, 
+                                  navigation: TodoItem.Owner, 
+                                  entity: entity, 
+                                  value: included[0])
+                              return Void AddToCollectionSnapshot(
+                                  stateManager: queryContext.StateManager, 
+                                  navigation: Person.TodoItems, 
+                                  entity: included[0], 
+                                  value: entity)
+                          }
+                           : default(Void)
+                      }
+                  )), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId", "model.Owner"."Id", "model.Owner"."FirstName", "model.Owner"."LastName"
+      FROM "TodoItems" AS "model"
+      LEFT JOIN "People" AS "model.Owner" ON "model"."OwnerId" = "model.Owner"."Id"
+      WHERE "model.Owner"."FirstName" = 'Crawford'
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId", "model.Owner"."Id", "model.Owner"."FirstName", "model.Owner"."LastName"
+      FROM "TodoItems" AS "model"
+      LEFT JOIN "People" AS "model.Owner" ON "model"."OwnerId" = "model.Owner"."Id"
+      WHERE "model.Owner"."FirstName" = 'Crawford'
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId", "model.Owner"."Id", "model.Owner"."FirstName", "model.Owner"."LastName"
+      FROM "TodoItems" AS "model"
+      LEFT JOIN "People" AS "model.Owner" ON "model"."OwnerId" = "model.Owner"."Id"
+      WHERE "model.Owner"."FirstName" = 'Crawford'
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 48.283ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 48.283ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 53.232ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 53.232ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner&filter[achieved-date]=2/18/18%2012:00:00%20AM  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner&filter[achieved-date]=2/18/18%2012:00:00%20AM  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Filter is not allowed for attribute 'achieved-date'.
+   at JsonApiDotNetCore.Internal.Query.AttrFilterQuery..ctor(IJsonApiContext jsonApiContext, FilterQuery filterQuery) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs:line 26
+   at JsonApiDotNetCore.Extensions.IQueryableExtensions.Filter[TSource](IQueryable`1 source, IJsonApiContext jsonApiContext, FilterQuery filterQuery) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs:line 88
+   at JsonApiDotNetCore.Data.DefaultEntityRepository`2.Filter(IQueryable`1 entities, FilterQuery filterQuery) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs:line 61
+   at JsonApiDotNetCore.Services.EntityResourceService`2.ApplySortAndFilterQuery(IQueryable`1 entities) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 156
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<GetAsync>d__4.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 46
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2.<GetAsync>d__12.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 109
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.JsonApiController`2.<GetAsync>d__3.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 62
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Filter is not allowed for attribute 'achieved-date'.
+   at JsonApiDotNetCore.Internal.Query.AttrFilterQuery..ctor(IJsonApiContext jsonApiContext, FilterQuery filterQuery) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs:line 26
+   at JsonApiDotNetCore.Extensions.IQueryableExtensions.Filter[TSource](IQueryable`1 source, IJsonApiContext jsonApiContext, FilterQuery filterQuery) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs:line 88
+   at JsonApiDotNetCore.Data.DefaultEntityRepository`2.Filter(IQueryable`1 entities, FilterQuery filterQuery) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs:line 61
+   at JsonApiDotNetCore.Services.EntityResourceService`2.ApplySortAndFilterQuery(IQueryable`1 entities) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 156
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<GetAsync>d__4.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 46
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2.<GetAsync>d__12.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 109
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.JsonApiController`2.<GetAsync>d__3.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 62
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 7.111ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 7.111ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 7.516ms 400 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 7.516ms 400 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?filter[guid-property]=a23f1cb2-5445-4cad-bda5-629ecc2002e2  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?filter[guid-property]=a23f1cb2-5445-4cad-bda5-629ecc2002e2  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].GuidProperty == a23f1cb2-5445-4cad-bda5-629ecc2002e2
+      select [model]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].GuidProperty == a23f1cb2-5445-4cad-bda5-629ecc2002e2
+      select [model]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "model"
+                          WHERE "model"."GuidProperty" = 'a23f1cb2-5445-4cad-bda5-629ecc2002e2'), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE "model"."GuidProperty" = 'a23f1cb2-5445-4cad-bda5-629ecc2002e2'
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE "model"."GuidProperty" = 'a23f1cb2-5445-4cad-bda5-629ecc2002e2'
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "model"
+      WHERE "model"."GuidProperty" = 'a23f1cb2-5445-4cad-bda5-629ecc2002e2'
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].GuidProperty == a23f1cb2-5445-4cad-bda5-629ecc2002e2
+      select [model])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem model in DbSet<TodoItem> where [model].GuidProperty == a23f1cb2-5445-4cad-bda5-629ecc...' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem model in DbSet<TodoItem> where [model].GuidProperty == a23f1cb2-5445-4cad-bda5-629ecc...' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where [model].GuidProperty == a23f1cb2-5445-4cad-bda5-629ecc2002e2
+      select [model])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+                      FROM "TodoItems" AS "model"
+                      WHERE "model"."GuidProperty" = 'a23f1cb2-5445-4cad-bda5-629ecc2002e2'
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE "model"."GuidProperty" = 'a23f1cb2-5445-4cad-bda5-629ecc2002e2'
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE "model"."GuidProperty" = 'a23f1cb2-5445-4cad-bda5-629ecc2002e2'
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."AchievedDate", "model"."AssigneeId", "model"."CollectionId", "model"."CreatedDate", "model"."Description", "model"."GuidProperty", "model"."Ordinal", "model"."OwnerId"
+      FROM "TodoItems" AS "model"
+      WHERE "model"."GuidProperty" = 'a23f1cb2-5445-4cad-bda5-629ecc2002e2'
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 11.26ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 11.26ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 17.365ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 17.365ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner&sort=achieved-date  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner&sort=achieved-date  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '2fce3eb8-46a5-44ed-9a98-55e95b5c8e2f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Sort is not allowed for attribute 'achieved-date'.
+   at JsonApiDotNetCore.Services.QueryParser.ParseSortParameters(String value) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 165
+   at JsonApiDotNetCore.Services.QueryParser.Parse(IQueryCollection query) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 51
+   at JsonApiDotNetCore.Services.JsonApiContext.ApplyContext[T](Object controller) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/JsonApiContext.cs:line 70
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 56
+   at JsonApiDotNetCore.Controllers.JsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 40
+   at JsonApiDotNetCore.Controllers.JsonApiController`1..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 17
+   at JsonApiDotNetCoreExample.Controllers.TodoItemsController..ctor(IJsonApiContext jsonApiContext, IResourceService`1 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsController.cs:line 14
+   at lambda_method(Closure , IServiceProvider , Object[] )
+   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Sort is not allowed for attribute 'achieved-date'.
+   at JsonApiDotNetCore.Services.QueryParser.ParseSortParameters(String value) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 165
+   at JsonApiDotNetCore.Services.QueryParser.Parse(IQueryCollection query) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 51
+   at JsonApiDotNetCore.Services.JsonApiContext.ApplyContext[T](Object controller) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/JsonApiContext.cs:line 70
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 56
+   at JsonApiDotNetCore.Controllers.JsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 40
+   at JsonApiDotNetCore.Controllers.JsonApiController`1..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 17
+   at JsonApiDotNetCoreExample.Controllers.TodoItemsController..ctor(IJsonApiContext jsonApiContext, IResourceService`1 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsController.cs:line 14
+   at lambda_method(Closure , IServiceProvider , Object[] )
+   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 6ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 6ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 6.407ms 400 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 6.407ms 400 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items application/vnd.api+json; charset=ISO-8859-4 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items application/vnd.api+json; charset=ISO-8859-4 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 0.891ms 415 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 0.891ms 415 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 0.468ms 406 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 0.468ms 406 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '05049b95-e09d-45ad-ad89-bee6f6e0f23b' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 58.963ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 58.963ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 78.167ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 78.167ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id 'd54e2950-a2b5-4f65-98a5-dd097888aa4b' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.Person) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.Person) - ModelState is Valid
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+System.InvalidCastException: Unable to cast object of type 'JsonApiDotNetCoreExample.Models.Person' to type 'JsonApiDotNetCoreExample.Models.TodoItem'.
+   at lambda_method(Closure , Object , Object[] )
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+System.InvalidCastException: Unable to cast object of type 'JsonApiDotNetCoreExample.Models.Person' to type 'JsonApiDotNetCoreExample.Models.TodoItem'.
+   at lambda_method(Closure , Object , Object[] )
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 11.067ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 11.067ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 26.767ms 409 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 26.767ms 409 application/vnd.api+json
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-collections application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-collections application/vnd.api+json 
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItemCollection) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItemCollection) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItemCollections" ("Id", "Name", "OwnerId")
+      VALUES (@p0, @p1, @p2);
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItemCollections" ("Id", "Name", "OwnerId")
+      VALUES (@p0, @p1, @p2);
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) in 93.607ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 119.596ms 201 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) in 93.607ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 119.596ms 201 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id 'e4bc225e-4ba0-4fca-a686-db10af6c6128' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.StatusCodeResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 403
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 403
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 5.173ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 5.173ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 20.262ms 403 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 20.262ms 403 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-collections application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-collections application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-collections'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.GetAsync (JsonApiDotNetCoreExample)' with id '21ae0180-661e-43c0-aaba-a63666b354fa' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItemCollection) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItemCollection) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItemCollections" ("Id", "Name", "OwnerId")
+      VALUES (@p0, @p1, @p2);
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItemCollections" ("Id", "Name", "OwnerId")
+      VALUES (@p0, @p1, @p2);
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItemCollections" ("Id", "Name", "OwnerId")
+      VALUES (@p0, @p1, @p2);
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.CreatedResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) in 58.596ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) in 58.596ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 77.468ms 201 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 77.468ms 201 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-collections application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-collections application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-collections'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.GetAsync (JsonApiDotNetCoreExample)' with id '3a8d48b8-e58c-4ef6-b4b3-166fd71553bc' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+fail: JsonApiDotNetCore.Formatters.JsonApiReader[0]
+      An error occurred while de-serializing the payload
+JsonApiDotNetCore.Internal.JsonApiException: Failed to deserialize request body ---> System.InvalidCastException: Unable to cast object of type 'System.Collections.Generic.List`1[JsonApiDotNetCore.Models.ResourceIdentifierObject]' to type 'System.Collections.Generic.List`1[System.Collections.Generic.Dictionary`2[System.String,System.Object]]'.
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.SetHasManyRelationship(Object entity, PropertyInfo[] entityProperties, RelationshipAttribute attr, ContextEntity contextEntity, Dictionary`2 relationships) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 216
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.SetRelationships(Object entity, ContextEntity contextEntity, Dictionary`2 relationships) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 156
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.DocumentToObject(DocumentData data) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 92
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(String requestBody) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 33
+   --- End of inner exception stack trace ---
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(String requestBody) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 38
+   at JsonApiDotNetCore.Formatters.JsonApiReader.ReadAsync(InputFormatterContext context) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs:line 39
+fail: JsonApiDotNetCore.Formatters.JsonApiReader[0]
+      An error occurred while de-serializing the payload
+JsonApiDotNetCore.Internal.JsonApiException: Failed to deserialize request body ---> System.InvalidCastException: Unable to cast object of type 'System.Collections.Generic.List`1[JsonApiDotNetCore.Models.ResourceIdentifierObject]' to type 'System.Collections.Generic.List`1[System.Collections.Generic.Dictionary`2[System.String,System.Object]]'.
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.SetHasManyRelationship(Object entity, PropertyInfo[] entityProperties, RelationshipAttribute attr, ContextEntity contextEntity, Dictionary`2 relationships) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 216
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.SetRelationships(Object entity, ContextEntity contextEntity, Dictionary`2 relationships) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 156
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.DocumentToObject(DocumentData data) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 92
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(String requestBody) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 33
+   --- End of inner exception stack trace ---
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(String requestBody) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 38
+   at JsonApiDotNetCore.Formatters.JsonApiReader.ReadAsync(InputFormatterContext context) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs:line 39
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) with arguments () - ModelState is Invalid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) with arguments () - ModelState is Invalid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.StatusCodeResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 422
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 422
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) in 22.188ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoCollectionsController.PostAsync (JsonApiDotNetCoreExample) in 22.188ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 42.033ms 422 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 42.033ms 422 
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+[xUnit.net 00:00:12.5112580]       JsonApiDotNetCore.Internal.JsonApiException : Failed to deserialize request body
+[xUnit.net 00:00:12.5115070]       ---- System.NullReferenceException : Object reference not set to an instance of an object.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+[xUnit.net 00:00:12.5136610]       Stack Trace:
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+[xUnit.net 00:00:12.5158820]         /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs(38,0): at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(String requestBody)
+[xUnit.net 00:00:12.5161330]         /Users/jarednance/dev/json-api-dotnet-core/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs(273,0): at JsonApiDotNetCoreExampleTests.Acceptance.Spec.CreatingDataTests.<Can_Create_And_Set_HasMany_Relationships>d__8.MoveNext()
+[xUnit.net 00:00:12.5165710]         --- End of stack trace from previous location where exception was thrown ---
+[xUnit.net 00:00:12.5167200]            at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+[xUnit.net 00:00:12.5168760]            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+[xUnit.net 00:00:12.5170850]         --- End of stack trace from previous location where exception was thrown ---
+[xUnit.net 00:00:12.5171820]            at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+[xUnit.net 00:00:12.5172640]            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+[xUnit.net 00:00:12.5174340]         --- End of stack trace from previous location where exception was thrown ---
+[xUnit.net 00:00:12.5175190]            at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+[xUnit.net 00:00:12.5175960]            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+[xUnit.net 00:00:12.5180580]         ----- Inner Stack Trace -----
+[xUnit.net 00:00:12.5182020]         /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs(32,0): at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(String requestBody)
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id '72eb1fba-bd67-40f7-841e-5d45f4d87655' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (11ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (11ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6)
+      RETURNING "Id", "CreatedDate";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.CreatedResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 78.019ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 102.786ms 201 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 78.019ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 102.786ms 201 application/vnd.api+json
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 POST http://localhost/api/v1/todo-items application/vnd.api+json 
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) with arguments (JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (11ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("Id", "AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (11ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("Id", "AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "CreatedDate";
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 72.862ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 94.538ms 201 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample) in 72.862ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 94.538ms 201 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).LastOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).LastOrDefault()'
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'LastOrDefault()' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'LastOrDefault()' could not be translated and will be evaluated locally.
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _TrackEntities(
+              results: IEnumerable<TodoItem> _ToSequence(TodoItem LastOrDefault(IEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                              FROM "TodoItems" AS "t", 
+                          shaper: UnbufferedEntityShaper<TodoItem>))), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/api/v1/todo-items/10099  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 DELETE http://localhost/api/v1/todo-items/10099  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id 'fe31e5b4-7432-4ff5-978a-cd27e2b93135' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '3c77838f-36d1-41ad-b93d-e79ea0456a72' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample) with arguments (10099) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample) with arguments (10099) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+                              FROM "TodoItems" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<TodoItem>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (16ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (16ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.NotFoundResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 404
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 404
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample) in 26.655ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample) in 26.655ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 58.036ms 404 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 58.036ms 404 
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2611?include=owner  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2611?include=owner  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id 'da4f66ae-3f53-4439-80dc-28886ee0c729' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id 'df4d22d4-25aa-4cc4-b517-33a346cabff2' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2611) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2611) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e])
+      .Include("Owner")
+      .FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[e].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      join Person e.Owner in DbSet<Person>
+      on Property([e], "OwnerId") equals (Nullable<int>)Property([e.Owner], "Id") into e.Owner_group
+      from Person e.Owner in 
+          (from Person e.Owner_groupItem in [e.Owner_group]
+          select [e.Owner_groupItem]).DefaultIfEmpty()
+      where bool [e].Id.Equals((object)__id_0)
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ [e.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      )).FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> FirstOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _Select(
+                          source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+                                  FROM "TodoItems" AS "e"
+                                  LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+                                  WHERE "e"."Id" = @__id_0
+                                  LIMIT 1, 
+                              shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                          selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                              queryContext: queryContext, 
+                              entity: t1.Outer, 
+                              included: new object[]{ t1.Inner }, 
+                              fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: TodoItem)
+                                  return !(bool ReferenceEquals(included[0], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[0], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Owner, 
+                                          entity: entity, 
+                                          value: included[0])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.TodoItems, 
+                                          entity: included[0], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                              }
+                          )), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 81.295ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 101.754ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 81.295ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 101.754ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p1;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p1;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p1;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '45c59ea2-28ca-4bbb-b184-0cd79d273bed' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 41.443ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 41.443ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 57.056ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 57.056ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2612/owner  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2612/owner  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}/{relationshipName}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample) with arguments (2612, owner) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample) with arguments (2612, owner) - ModelState is Valid
+trce: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Looking up 'Owner'...
+dbug: JsonApiDotNetCore.Data.DefaultEntityRepository[0]
+      [JADN] GetAndIncludeAsync(2612, Owner)
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in 
+          (from TodoItem <generated>_1 in DbSet<TodoItem>
+          select [<generated>_1]).Include("Owner")
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[<generated>_1].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      join Person e.Owner in DbSet<Person>
+      on Property([e], "OwnerId") equals (Nullable<int>)Property([e.Owner], "Id") into e.Owner_group
+      from Person e.Owner in 
+          (from Person e.Owner_groupItem in [e.Owner_group]
+          select [e.Owner_groupItem]).DefaultIfEmpty()
+      where bool [e].Id.Equals((object)__id_0)
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ [e.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      )).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _Select(
+                          source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+                                  FROM "TodoItems" AS "e"
+                                  LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+                                  WHERE "e"."Id" = @__id_0
+                                  LIMIT 2, 
+                              shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                          selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                              queryContext: queryContext, 
+                              entity: t1.Outer, 
+                              included: new object[]{ t1.Inner }, 
+                              fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: TodoItem)
+                                  return !(bool ReferenceEquals(included[0], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[0], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Owner, 
+                                          entity: entity, 
+                                          value: included[0])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.TodoItems, 
+                                          entity: included[0], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                              }
+                          )), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Relationship Owner not found.
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<GetRelationshipAsync>d__9.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 102
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2.<GetRelationshipAsync>d__15.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 141
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.JsonApiController`2.<GetRelationshipAsync>d__6.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 73
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Relationship Owner not found.
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<GetRelationshipAsync>d__9.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 102
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2.<GetRelationshipAsync>d__15.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 141
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.JsonApiController`2.<GetRelationshipAsync>d__6.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 73
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample) in 58.256ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample) in 58.256ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 78.585ms 404 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 78.585ms 404 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+Failed   JsonApiDotNetCoreExampleTests.Acceptance.Spec.CreatingDataTests.Can_Create_And_Set_HasMany_Relationships
+Error Message:
+ JsonApiDotNetCore.Internal.JsonApiException : Failed to deserialize request body
+---- System.NullReferenceException : Object reference not set to an instance of an object.
+Stack Trace:
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(String requestBody) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 38
+   at JsonApiDotNetCoreExampleTests.Acceptance.Spec.CreatingDataTests.<Can_Create_And_Set_HasMany_Relationships>d__8.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs:line 273
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+----- Inner Stack Trace -----
+   at JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(String requestBody) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs:line 32
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2613/owner  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2613/owner  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}/{relationshipName}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample) with arguments (2613, owner) - ModelState is Valid
+trce: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Looking up 'Owner'...
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample) with arguments (2613, owner) - ModelState is Valid
+dbug: JsonApiDotNetCore.Data.DefaultEntityRepository[0]
+      [JADN] GetAndIncludeAsync(2613, Owner)
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in 
+          (from TodoItem <generated>_1 in DbSet<TodoItem>
+          select [<generated>_1]).Include("Owner")
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[<generated>_1].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      join Person e.Owner in DbSet<Person>
+      on Property([e], "OwnerId") equals (Nullable<int>)Property([e.Owner], "Id") into e.Owner_group
+      from Person e.Owner in 
+          (from Person e.Owner_groupItem in [e.Owner_group]
+          select [e.Owner_groupItem]).DefaultIfEmpty()
+      where bool [e].Id.Equals((object)__id_0)
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ [e.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      )).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _Select(
+                          source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+                                  FROM "TodoItems" AS "e"
+                                  LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+                                  WHERE "e"."Id" = @__id_0
+                                  LIMIT 2, 
+                              shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                          selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                              queryContext: queryContext, 
+                              entity: t1.Outer, 
+                              included: new object[]{ t1.Inner }, 
+                              fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: TodoItem)
+                                  return !(bool ReferenceEquals(included[0], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[0], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Owner, 
+                                          entity: entity, 
+                                          value: included[0])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.TodoItems, 
+                                          entity: included[0], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                              }
+                          )), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (11ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (11ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample) in 56.604ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipAsync (JsonApiDotNetCoreExample) in 56.604ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 74.256ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 74.256ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?unknownKey=value  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?unknownKey=value  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '154c85f6-801d-4115-8e42-da8fe75f1bea' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: [unknownKey, value] is not a valid query.
+   at JsonApiDotNetCore.Services.QueryParser.Parse(IQueryCollection query) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 75
+   at JsonApiDotNetCore.Services.JsonApiContext.ApplyContext[T](Object controller) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/JsonApiContext.cs:line 70
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 56
+   at JsonApiDotNetCore.Controllers.JsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 40
+   at JsonApiDotNetCore.Controllers.JsonApiController`1..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 17
+   at JsonApiDotNetCoreExample.Controllers.TodoItemsController..ctor(IJsonApiContext jsonApiContext, IResourceService`1 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsController.cs:line 14
+   at lambda_method(Closure , IServiceProvider , Object[] )
+   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: [unknownKey, value] is not a valid query.
+   at JsonApiDotNetCore.Services.QueryParser.Parse(IQueryCollection query) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 75
+   at JsonApiDotNetCore.Services.JsonApiContext.ApplyContext[T](Object controller) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/JsonApiContext.cs:line 70
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 56
+   at JsonApiDotNetCore.Controllers.JsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 40
+   at JsonApiDotNetCore.Controllers.JsonApiController`1..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 17
+   at JsonApiDotNetCoreExample.Controllers.TodoItemsController..ctor(IJsonApiContext jsonApiContext, IResourceService`1 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsController.cs:line 14
+   at lambda_method(Closure , IServiceProvider , Object[] )
+   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 4.858ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 4.858ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 24.057ms 400 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 24.057ms 400 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2614?fields[todo-items]=description,created-date  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2614?fields[todo-items]=description,created-date  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id 'ce1f18f1-2c9d-469e-8706-cdda1d627b0c' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '736779bb-b124-40ac-a9e5-58f8ea4bdcc3' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2614) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2614) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where bool new TodoItem{ 
+          Id = [model].Id, 
+          Description = [model].Description, 
+          CreatedDate = [model].CreatedDate 
+      }
+      .Id.Equals((object)__id_0)
+      select new TodoItem{ 
+          Id = [model].Id, 
+          Description = [model].Description, 
+          CreatedDate = [model].CreatedDate 
+      }
+      ).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem model in DbSet<TodoItem>
+      where bool new TodoItem{ 
+          Id = [model].Id, 
+          Description = [model].Description, 
+          CreatedDate = [model].CreatedDate 
+      }
+      .Id.Equals((object)__id_0)
+      select new TodoItem{ 
+          Id = [model].Id, 
+          Description = [model].Description, 
+          CreatedDate = [model].CreatedDate 
+      }
+      ).SingleOrDefault()'
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'where new TodoItem() {Id = [model].Id, Description = [model].Description, CreatedDate = [model].CreatedDate}.Id.Equals(Convert(__id_0, Object))' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'where new TodoItem() {Id = [model].Id, Description = [model].Description, CreatedDate = [model].CreatedDate}.Id.Equals(Convert(__id_0, Object))' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'SingleOrDefault()' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'SingleOrDefault()' could not be translated and will be evaluated locally.
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                  source: IAsyncEnumerable<TodoItem> _Select(
+                      source: IAsyncEnumerable<ValueBuffer> _Where(
+                          source: IAsyncEnumerable<ValueBuffer> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "model"."Id", "model"."Description", "model"."CreatedDate"
+                                  FROM "TodoItems" AS "model", 
+                              shaper: ValueBufferShaper), 
+                          predicate: (ValueBuffer model) => bool new TodoItem{ 
+                              Id = int TryReadValue(model, 0, TodoItem.Id), 
+                              Description = string TryReadValue(model, 1, TodoItem.Description), 
+                              CreatedDate = DateTime TryReadValue(model, 2, TodoItem.CreatedDate) 
+                          }
+                          .Id.Equals((object)int GetParameterValue(
+                                  queryContext: queryContext, 
+                                  parameterName: "__id_0"))), 
+                      selector: (ValueBuffer model) => new TodoItem{ 
+                          Id = int TryReadValue(model, 0, TodoItem.Id), 
+                          Description = string TryReadValue(model, 1, TodoItem.Description), 
+                          CreatedDate = DateTime TryReadValue(model, 2, TodoItem.CreatedDate) 
+                      }
+                  ), 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."Description", "model"."CreatedDate"
+      FROM "TodoItems" AS "model"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."Description", "model"."CreatedDate"
+      FROM "TodoItems" AS "model"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "model"."Id", "model"."Description", "model"."CreatedDate"
+      FROM "TodoItems" AS "model"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 105.374ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 105.374ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 125.325ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 125.325ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      'from TodoItem t in DbSet<TodoItem>
+      where [t].Id == 2615
+      select new TodoItem{ 
+          Id = [t].Id, 
+          Description = [t].Description, 
+          CreatedDate = [t].CreatedDate, 
+          AchievedDate = [t].AchievedDate 
+      }
+      '
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      'from TodoItem t in DbSet<TodoItem>
+      where [t].Id == 2615
+      select new TodoItem{ 
+          Id = [t].Id, 
+          Description = [t].Description, 
+          CreatedDate = [t].CreatedDate, 
+          AchievedDate = [t].AchievedDate 
+      }
+      '
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _ShapedQuery(
+              queryContext: queryContext, 
+              shaperCommandContext: SelectExpression: 
+                  SELECT "t"."Id", "t"."Description", "t"."CreatedDate", "t"."AchievedDate"
+                  FROM "TodoItems" AS "t"
+                  WHERE "t"."Id" = 2615, 
+              shaper: TypedProjectionShaper<ValueBufferShaper, ValueBuffer, TodoItem>), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem t in DbSet<TodoItem>
+      where [t].Id == __todoItem_Id_0
+      select new TodoItem{ 
+          Id = [t].Id, 
+          Description = [t].Description, 
+          CreatedDate = [t].CreatedDate, 
+          AchievedDate = [t].AchievedDate 
+      }
+      ).First()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem t in DbSet<TodoItem>
+      where [t].Id == __todoItem_Id_0
+      select new TodoItem{ 
+          Id = [t].Id, 
+          Description = [t].Description, 
+          CreatedDate = [t].CreatedDate, 
+          AchievedDate = [t].AchievedDate 
+      }
+      ).First()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> First(
+                  source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT "t"."Id", "t"."Description", "t"."CreatedDate", "t"."AchievedDate"
+                          FROM "TodoItems" AS "t"
+                          WHERE "t"."Id" = @__todoItem_Id_0
+                          LIMIT 1, 
+                      shaper: TypedProjectionShaper<ValueBufferShaper, ValueBuffer, TodoItem>), 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."Description", "t"."CreatedDate", "t"."AchievedDate"
+      FROM "TodoItems" AS "t"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."Description", "t"."CreatedDate", "t"."AchievedDate"
+      FROM "TodoItems" AS "t"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."Description", "t"."CreatedDate", "t"."AchievedDate"
+      FROM "TodoItems" AS "t"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2616 application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2616 application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id '99416189-fd56-43fd-accb-b675b7d46314' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '7d80e15e-9750-4047-b86c-88bfc61fd12f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2616, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2616, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+                              FROM "TodoItems" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<TodoItem>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (11ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (11ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 95.019ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 95.019ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 116.16ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 116.16ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem t in 
+          (from TodoItem <generated>_1 in DbSet<TodoItem>
+          select [<generated>_1])
+          .AsNoTracking()
+          .Include("Owner")
+      where [t].Id == __todoItem_Id_0
+      select [t]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[<generated>_1].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem t in DbSet<TodoItem>
+      join Person t.Owner in DbSet<Person>
+      on Property([t], "OwnerId") equals (Nullable<int>)Property([t.Owner], "Id") into t.Owner_group
+      from Person t.Owner in 
+          (from Person t.Owner_groupItem in [t.Owner_group]
+          select [t.Owner_groupItem]).DefaultIfEmpty()
+      where [t].Id == __todoItem_Id_0
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [t], 
+          included: new object[]{ [t.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  entity.Owner = (Person)included[0]
+                  return bool ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>.Add(
+                      instance: included[0], 
+                      value: entity)
+              }
+               : default(bool)
+          }
+      )).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _ToSequence(TodoItem SingleOrDefault(IEnumerable<TodoItem> _Select(
+                      source: IEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+                              FROM "TodoItems" AS "t"
+                              LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+                              WHERE "t"."Id" = @__todoItem_Id_0
+                              LIMIT 2, 
+                          shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                      selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                          queryContext: queryContext, 
+                          entity: t1.Outer, 
+                          included: new object[]{ t1.Inner }, 
+                          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                          {
+                              return !(bool ReferenceEquals(included[0], null)) ? 
+                              {
+                                  entity.Owner = (Person)included[0]
+                                  return bool ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>.Add(
+                                      instance: included[0], 
+                                      value: entity)
+                              }
+                               : default(bool)
+                          }
+                      )))), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2716 application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2716 application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)' with id '2a9a328a-ccd2-441f-86b9-778e783257c7' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id 'f400e30f-a558-41ca-9432-b889d803f5d2' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2716, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) with arguments (2716, JsonApiDotNetCoreExample.Models.TodoItem) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+                              FROM "TodoItems" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<TodoItem>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.NotFoundResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 404
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 404
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 27.817ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample) in 27.817ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 47.257ms 404 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 47.257ms 404 
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2617/relationships/owner application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/todo-items/2617/relationships/owner application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}/relationships/{relationshipName}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetRelationshipsAsync (JsonApiDotNetCoreExample)' with id '3fde0ec7-9039-455f-910c-e568544f788a' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchRelationshipsAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchRelationshipsAsync (JsonApiDotNetCoreExample) with arguments (2617, owner, System.Collections.Generic.List`1[JsonApiDotNetCore.Models.DocumentData]) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchRelationshipsAsync (JsonApiDotNetCoreExample) with arguments (2617, owner, System.Collections.Generic.List`1[JsonApiDotNetCore.Models.DocumentData]) - ModelState is Valid
+dbug: JsonApiDotNetCore.Data.DefaultEntityRepository[0]
+      [JADN] GetAndIncludeAsync(2617, Owner)
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in 
+          (from TodoItem <generated>_1 in DbSet<TodoItem>
+          select [<generated>_1]).Include("Owner")
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[<generated>_1].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      join Person e.Owner in DbSet<Person>
+      on Property([e], "OwnerId") equals (Nullable<int>)Property([e.Owner], "Id") into e.Owner_group
+      from Person e.Owner in 
+          (from Person e.Owner_groupItem in [e.Owner_group]
+          select [e.Owner_groupItem]).DefaultIfEmpty()
+      where bool [e].Id.Equals((object)__id_0)
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ [e.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      )).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _Select(
+                          source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+                                  FROM "TodoItems" AS "e"
+                                  LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+                                  WHERE "e"."Id" = @__id_0
+                                  LIMIT 2, 
+                              shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                          selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                              queryContext: queryContext, 
+                              entity: t1.Outer, 
+                              included: new object[]{ t1.Inner }, 
+                              fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: TodoItem)
+                                  return !(bool ReferenceEquals(included[0], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[0], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Owner, 
+                                          entity: entity, 
+                                          value: included[0])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.TodoItems, 
+                                          entity: included[0], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                              }
+                          )), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (12ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (12ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person x in DbSet<Person>
+      where __First_0 == [x].StringId
+      select [x]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person x in DbSet<Person>
+      where __First_0 == [x].StringId
+      select [x]).SingleOrDefault()'
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'where (__First_0 == [x].StringId)' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'where (__First_0 == [x].StringId)' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'SingleOrDefault()' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'SingleOrDefault()' could not be translated and will be evaluated locally.
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<Person> _InterceptExceptions(
+          source: IEnumerable<Person> _TrackEntities(
+              results: IEnumerable<Person> _ToSequence(Person SingleOrDefault(IEnumerable<Person> _Where(
+                          source: IEnumerable<Person> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "x"."Id", "x"."FirstName", "x"."LastName"
+                                  FROM "People" AS "x", 
+                              shaper: UnbufferedEntityShaper<Person>), 
+                          predicate: (Person x) => string GetParameterValue(
+                              queryContext: queryContext, 
+                              parameterName: "__First_0") == x.StringId))), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."FirstName", "x"."LastName"
+      FROM "People" AS "x"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."FirstName", "x"."LastName"
+      FROM "People" AS "x"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."FirstName", "x"."LastName"
+      FROM "People" AS "x"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchRelationshipsAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchRelationshipsAsync (JsonApiDotNetCoreExample) in 128.36ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchRelationshipsAsync (JsonApiDotNetCoreExample) in 128.36ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 147.825ms 200 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 147.825ms 200 
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem t in 
+          (from TodoItem t in DbSet<TodoItem>
+          select [t]).Include("Owner")
+      where [t].Id == __todoItem_Id_0
+      select [t]).Single()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[t].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem t in DbSet<TodoItem>
+      join Person t.Owner in DbSet<Person>
+      on Property([t], "OwnerId") equals (Nullable<int>)Property([t.Owner], "Id") into t.Owner_group
+      from Person t.Owner in 
+          (from Person t.Owner_groupItem in [t.Owner_group]
+          select [t.Owner_groupItem]).DefaultIfEmpty()
+      where [t].Id == __todoItem_Id_0
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [t], 
+          included: new object[]{ [t.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      )).Single()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _TrackEntities(
+              results: IEnumerable<TodoItem> _ToSequence(TodoItem Single(IEnumerable<TodoItem> _Select(
+                          source: IEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+                                  FROM "TodoItems" AS "t"
+                                  LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+                                  WHERE "t"."Id" = @__todoItem_Id_0
+                                  LIMIT 2, 
+                              shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                          selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                              queryContext: queryContext, 
+                              entity: t1.Outer, 
+                              included: new object[]{ t1.Inner }, 
+                              fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: TodoItem)
+                                  return !(bool ReferenceEquals(included[0], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[0], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Owner, 
+                                          entity: entity, 
+                                          value: included[0])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.TodoItems, 
+                                          entity: included[0], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                              }
+                          )))), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__todoItem_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      WHERE "t"."Id" = @__todoItem_Id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/people/887/relationships/todo-items application/vnd.api+json 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 PATCH http://localhost/api/v1/people/887/relationships/todo-items application/vnd.api+json 
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people/{id}/relationships/{relationshipName}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.GetRelationshipsAsync (JsonApiDotNetCoreExample)' with id '55bc06aa-666a-4e45-9dba-c3c04b1e2592' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.PatchRelationshipsAsync (JsonApiDotNetCoreExample)
+dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[1]
+      Selected input formatter 'JsonApiDotNetCore.Formatters.JsonApiInputFormatter' for content type 'application/vnd.api+json'.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.PatchRelationshipsAsync (JsonApiDotNetCoreExample) with arguments (887, todo-items, System.Collections.Generic.List`1[JsonApiDotNetCore.Models.DocumentData]) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.PatchRelationshipsAsync (JsonApiDotNetCoreExample) with arguments (887, todo-items, System.Collections.Generic.List`1[JsonApiDotNetCore.Models.DocumentData]) - ModelState is Valid
+dbug: JsonApiDotNetCore.Data.DefaultEntityRepository[0]
+      [JADN] GetAndIncludeAsync(887, TodoItems)
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person e in 
+          (from Person <generated>_1 in DbSet<Person>
+          select [<generated>_1]).Include("TodoItems")
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[<generated>_1].TodoItems'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person e in DbSet<Person>
+      where bool [e].Id.Equals((object)__id_0)
+      order by (Nullable<int>)EF.Property(?[e]?, "Id") asc
+      select Task<Person> _IncludeAsync(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ }, 
+          fixup: (QueryContext queryContext | Person entity | Object[] included | CancellationToken ct) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: Person)
+              return Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                  includeId: 0, 
+                  navigation: Person.TodoItems, 
+                  inverseNavigation: TodoItem.Owner, 
+                  targetEntityType: EntityType: TodoItem, 
+                  clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                  inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                  tracking: True, 
+                  instance: entity, 
+                  valuesFactory: (Func<IAsyncEnumerable<object>>)() => 
+                      from TodoItem e.TodoItems in DbSet<TodoItem>
+                      join AnonymousObject _e in 
+                          (from Person e in DbSet<Person>
+                          where bool [e].Id.Equals((object)__id_0)
+                          order by (Nullable<int>)EF.Property(?[e]?, "Id") asc
+                          select new AnonymousObject(new object[]{ (object)EF.Property(?[e]?, "Id") })).Take(1)
+                      on Property([e.TodoItems], "OwnerId") equals (Nullable<int>)object [_e].GetValue(0)
+                      order by object [_e].GetValue(0) asc
+                      select [e.TodoItems], 
+                  cancellationToken: ct)
+          }
+          , 
+          cancellationToken: ct).Result).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<Person> _InterceptExceptions(
+          source: IAsyncEnumerable<Person> _TrackEntities(
+              results: IAsyncEnumerable<Person> _ToSequence(Task<Person> SingleOrDefault(
+                      source: IAsyncEnumerable<Person> _SelectAsync(
+                          source: IAsyncEnumerable<Person> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+                                  FROM "People" AS "e"
+                                  WHERE "e"."Id" = @__id_0
+                                  ORDER BY "e"."Id"
+                                  LIMIT 2, 
+                              shaper: BufferedEntityShaper<Person>), 
+                          selector: (Person e | CancellationToken ct) => Task<Person> _ExecuteAsync(
+                              taskFactories: new Func<Task<object>>[]{ () => Task<object> _ToObjectTask(Task<Person> _IncludeAsync(
+                                          queryContext: queryContext, 
+                                          entity: e, 
+                                          included: new object[]{ }, 
+                                          fixup: (QueryContext queryContext | Person entity | Object[] included | CancellationToken ct) => 
+                                          {
+                                              Void queryContext.QueryBuffer.StartTracking(
+                                                  entity: entity, 
+                                                  entityType: EntityType: Person)
+                                              return Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                                                  includeId: 0, 
+                                                  navigation: Person.TodoItems, 
+                                                  inverseNavigation: TodoItem.Owner, 
+                                                  targetEntityType: EntityType: TodoItem, 
+                                                  clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                                                  inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                                                  tracking: True, 
+                                                  instance: entity, 
+                                                  valuesFactory: (Func<IAsyncEnumerable<object>>)() => IAsyncEnumerable<TodoItem> _ShapedQuery(
+                                                      queryContext: queryContext, 
+                                                      shaperCommandContext: SelectExpression: 
+                                                          SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+                                                          FROM "TodoItems" AS "e.TodoItems"
+                                                          INNER JOIN (
+                                                              SELECT "e0"."Id"
+                                                              FROM "People" AS "e0"
+                                                              WHERE "e0"."Id" = @__id_0
+                                                              ORDER BY "e0"."Id"
+                                                              LIMIT 1
+                                                          ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+                                                          ORDER BY "t"."Id", 
+                                                      shaper: BufferedEntityShaper<TodoItem>), 
+                                                  cancellationToken: ct)
+                                          }
+                                          , 
+                                          cancellationToken: Unhandled parameter: ct)) }, 
+                              selector: (Object[] results) => (Person)results[0])), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      'from TodoItem x in DbSet<TodoItem>
+      where 
+          (from string <generated>_1 in __relationshipIds_0
+          select [<generated>_1]).Contains([x].StringId)
+      select [x]'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      'from TodoItem x in DbSet<TodoItem>
+      where 
+          (from string <generated>_1 in __relationshipIds_0
+          select [<generated>_1]).Contains([x].StringId)
+      select [x]'
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'where {__relationshipIds_0 => Contains([x].StringId)}' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'where {__relationshipIds_0 => Contains([x].StringId)}' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'Contains([x].StringId)' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'Contains([x].StringId)' could not be translated and will be evaluated locally.
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _TrackEntities(
+              results: IEnumerable<TodoItem> _Where(
+                  source: IEnumerable<TodoItem> _ShapedQuery(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+                          FROM "TodoItems" AS "x", 
+                      shaper: UnbufferedEntityShaper<TodoItem>), 
+                  predicate: (TodoItem x) => bool Contains(
+                      source: IEnumerable<string> GetParameterValue(
+                          queryContext: queryContext, 
+                          parameterName: "__relationshipIds_0"), 
+                      value: x.StringId)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "x"."Id", "x"."AchievedDate", "x"."AssigneeId", "x"."CollectionId", "x"."CreatedDate", "x"."Description", "x"."GuidProperty", "x"."Ordinal", "x"."OwnerId"
+      FROM "TodoItems" AS "x"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30']
+      UPDATE "TodoItems" SET "OwnerId" = @p0
+      WHERE "Id" = @p1;
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.PeopleController.PatchRelationshipsAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkResult.
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
+      Executing HttpStatusCodeResult, setting HTTP status code 200
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.PatchRelationshipsAsync (JsonApiDotNetCoreExample) in 222.821ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.PatchRelationshipsAsync (JsonApiDotNetCoreExample) in 222.821ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 254.919ms 200 
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 254.919ms 200 
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person p in 
+          (from Person p in DbSet<Person>
+          select [p]).Include("TodoItems")
+      where [p].Id == __person_Id_0
+      select [p]).Single()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[p].TodoItems'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person p in DbSet<Person>
+      where [p].Id == __person_Id_0
+      order by (Nullable<int>)EF.Property(?[p]?, "Id") asc
+      select Person _Include(
+          queryContext: queryContext, 
+          entity: [p], 
+          included: new object[]{ }, 
+          fixup: (QueryContext queryContext | Person entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: Person)
+              return Void queryContext.QueryBuffer.IncludeCollection(
+                  includeId: 0, 
+                  navigation: Person.TodoItems, 
+                  inverseNavigation: TodoItem.Owner, 
+                  targetEntityType: EntityType: TodoItem, 
+                  clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                  inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                  tracking: True, 
+                  instance: entity, 
+                  valuesFactory: () => 
+                      from TodoItem p.TodoItems in DbSet<TodoItem>
+                      join AnonymousObject _p in 
+                          (from Person p in DbSet<Person>
+                          where [p].Id == __person_Id_0
+                          order by (Nullable<int>)EF.Property(?[p]?, "Id") asc
+                          select new AnonymousObject(new object[]{ (object)EF.Property(?[p]?, "Id") })).Take(1)
+                      on Property([p.TodoItems], "OwnerId") equals (Nullable<int>)object [_p].GetValue(0)
+                      order by object [_p].GetValue(0) asc
+                      select [p.TodoItems])
+          }
+      )).Single()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<Person> _InterceptExceptions(
+          source: IEnumerable<Person> _TrackEntities(
+              results: IEnumerable<Person> _ToSequence(Person Single(IEnumerable<Person> _Select(
+                          source: IEnumerable<Person> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+                                  FROM "People" AS "p"
+                                  WHERE "p"."Id" = @__person_Id_0
+                                  ORDER BY "p"."Id"
+                                  LIMIT 2, 
+                              shaper: BufferedEntityShaper<Person>), 
+                          selector: (Person p) => Person _Include(
+                              queryContext: queryContext, 
+                              entity: p, 
+                              included: new object[]{ }, 
+                              fixup: (QueryContext queryContext | Person entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: Person)
+                                  return Void queryContext.QueryBuffer.IncludeCollection(
+                                      includeId: 0, 
+                                      navigation: Person.TodoItems, 
+                                      inverseNavigation: TodoItem.Owner, 
+                                      targetEntityType: EntityType: TodoItem, 
+                                      clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                                      inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                                      tracking: True, 
+                                      instance: entity, 
+                                      valuesFactory: () => IEnumerable<TodoItem> _ShapedQuery(
+                                          queryContext: queryContext, 
+                                          shaperCommandContext: SelectExpression: 
+                                              SELECT "p.TodoItems"."Id", "p.TodoItems"."AchievedDate", "p.TodoItems"."AssigneeId", "p.TodoItems"."CollectionId", "p.TodoItems"."CreatedDate", "p.TodoItems"."Description", "p.TodoItems"."GuidProperty", "p.TodoItems"."Ordinal", "p.TodoItems"."OwnerId"
+                                              FROM "TodoItems" AS "p.TodoItems"
+                                              INNER JOIN (
+                                                  SELECT "p0"."Id"
+                                                  FROM "People" AS "p0"
+                                                  WHERE "p0"."Id" = @__person_Id_0
+                                                  ORDER BY "p0"."Id"
+                                                  LIMIT 1
+                                              ) AS "t" ON "p.TodoItems"."OwnerId" = "t"."Id"
+                                              ORDER BY "t"."Id", 
+                                          shaper: BufferedEntityShaper<TodoItem>))
+                              }
+                          )))), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__person_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      WHERE "p"."Id" = @__person_Id_0
+      ORDER BY "p"."Id"
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__person_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      WHERE "p"."Id" = @__person_Id_0
+      ORDER BY "p"."Id"
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__person_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      WHERE "p"."Id" = @__person_Id_0
+      ORDER BY "p"."Id"
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__person_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p.TodoItems"."Id", "p.TodoItems"."AchievedDate", "p.TodoItems"."AssigneeId", "p.TodoItems"."CollectionId", "p.TodoItems"."CreatedDate", "p.TodoItems"."Description", "p.TodoItems"."GuidProperty", "p.TodoItems"."Ordinal", "p.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "p.TodoItems"
+      INNER JOIN (
+          SELECT "p0"."Id"
+          FROM "People" AS "p0"
+          WHERE "p0"."Id" = @__person_Id_0
+          ORDER BY "p0"."Id"
+          LIMIT 1
+      ) AS "t" ON "p.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__person_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p.TodoItems"."Id", "p.TodoItems"."AchievedDate", "p.TodoItems"."AssigneeId", "p.TodoItems"."CollectionId", "p.TodoItems"."CreatedDate", "p.TodoItems"."Description", "p.TodoItems"."GuidProperty", "p.TodoItems"."Ordinal", "p.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "p.TodoItems"
+      INNER JOIN (
+          SELECT "p0"."Id"
+          FROM "People" AS "p0"
+          WHERE "p0"."Id" = @__person_Id_0
+          ORDER BY "p0"."Id"
+          LIMIT 1
+      ) AS "t" ON "p.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__person_Id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p.TodoItems"."Id", "p.TodoItems"."AchievedDate", "p.TodoItems"."AssigneeId", "p.TodoItems"."CollectionId", "p.TodoItems"."CreatedDate", "p.TodoItems"."Description", "p.TodoItems"."GuidProperty", "p.TodoItems"."Ordinal", "p.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "p.TodoItems"
+      INNER JOIN (
+          SELECT "p0"."Id"
+          FROM "People" AS "p0"
+          WHERE "p0"."Id" = @__person_Id_0
+          ORDER BY "p0"."Id"
+          LIMIT 1
+      ) AS "t" ON "p.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      'from Person <generated>_0 in DbSet<Person>
+      select [<generated>_0]'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      'from Person <generated>_0 in DbSet<Person>
+      select [<generated>_0]'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<Person> _InterceptExceptions(
+          source: IEnumerable<Person> _TrackEntities(
+              results: IEnumerable<Person> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+                      FROM "People" AS "p", 
+                  shaper: UnbufferedEntityShaper<Person>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p0;
+      DELETE FROM "People"
+      WHERE "Id" = @p1;
+      DELETE FROM "People"
+      WHERE "Id" = @p2;
+      DELETE FROM "People"
+      WHERE "Id" = @p3;
+      DELETE FROM "People"
+      WHERE "Id" = @p4;
+      DELETE FROM "People"
+      WHERE "Id" = @p5;
+      DELETE FROM "People"
+      WHERE "Id" = @p6;
+      DELETE FROM "People"
+      WHERE "Id" = @p7;
+      DELETE FROM "People"
+      WHERE "Id" = @p8;
+      DELETE FROM "People"
+      WHERE "Id" = @p9;
+      DELETE FROM "People"
+      WHERE "Id" = @p10;
+      DELETE FROM "People"
+      WHERE "Id" = @p11;
+      DELETE FROM "People"
+      WHERE "Id" = @p12;
+      DELETE FROM "People"
+      WHERE "Id" = @p13;
+      DELETE FROM "People"
+      WHERE "Id" = @p14;
+      DELETE FROM "People"
+      WHERE "Id" = @p15;
+      DELETE FROM "People"
+      WHERE "Id" = @p16;
+      DELETE FROM "People"
+      WHERE "Id" = @p17;
+      DELETE FROM "People"
+      WHERE "Id" = @p18;
+      DELETE FROM "People"
+      WHERE "Id" = @p19;
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p20, @p21)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p0;
+      DELETE FROM "People"
+      WHERE "Id" = @p1;
+      DELETE FROM "People"
+      WHERE "Id" = @p2;
+      DELETE FROM "People"
+      WHERE "Id" = @p3;
+      DELETE FROM "People"
+      WHERE "Id" = @p4;
+      DELETE FROM "People"
+      WHERE "Id" = @p5;
+      DELETE FROM "People"
+      WHERE "Id" = @p6;
+      DELETE FROM "People"
+      WHERE "Id" = @p7;
+      DELETE FROM "People"
+      WHERE "Id" = @p8;
+      DELETE FROM "People"
+      WHERE "Id" = @p9;
+      DELETE FROM "People"
+      WHERE "Id" = @p10;
+      DELETE FROM "People"
+      WHERE "Id" = @p11;
+      DELETE FROM "People"
+      WHERE "Id" = @p12;
+      DELETE FROM "People"
+      WHERE "Id" = @p13;
+      DELETE FROM "People"
+      WHERE "Id" = @p14;
+      DELETE FROM "People"
+      WHERE "Id" = @p15;
+      DELETE FROM "People"
+      WHERE "Id" = @p16;
+      DELETE FROM "People"
+      WHERE "Id" = @p17;
+      DELETE FROM "People"
+      WHERE "Id" = @p18;
+      DELETE FROM "People"
+      WHERE "Id" = @p19;
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p20, @p21)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p0;
+      DELETE FROM "People"
+      WHERE "Id" = @p1;
+      DELETE FROM "People"
+      WHERE "Id" = @p2;
+      DELETE FROM "People"
+      WHERE "Id" = @p3;
+      DELETE FROM "People"
+      WHERE "Id" = @p4;
+      DELETE FROM "People"
+      WHERE "Id" = @p5;
+      DELETE FROM "People"
+      WHERE "Id" = @p6;
+      DELETE FROM "People"
+      WHERE "Id" = @p7;
+      DELETE FROM "People"
+      WHERE "Id" = @p8;
+      DELETE FROM "People"
+      WHERE "Id" = @p9;
+      DELETE FROM "People"
+      WHERE "Id" = @p10;
+      DELETE FROM "People"
+      WHERE "Id" = @p11;
+      DELETE FROM "People"
+      WHERE "Id" = @p12;
+      DELETE FROM "People"
+      WHERE "Id" = @p13;
+      DELETE FROM "People"
+      WHERE "Id" = @p14;
+      DELETE FROM "People"
+      WHERE "Id" = @p15;
+      DELETE FROM "People"
+      WHERE "Id" = @p16;
+      DELETE FROM "People"
+      WHERE "Id" = @p17;
+      DELETE FROM "People"
+      WHERE "Id" = @p18;
+      DELETE FROM "People"
+      WHERE "Id" = @p19;
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p20, @p21)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p28;
+      DELETE FROM "People"
+      WHERE "Id" = @p29;
+      DELETE FROM "People"
+      WHERE "Id" = @p30;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p31, @p32, @p33, @p34, @p35, @p36, @p37, @p38)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p28;
+      DELETE FROM "People"
+      WHERE "Id" = @p29;
+      DELETE FROM "People"
+      WHERE "Id" = @p30;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p31, @p32, @p33, @p34, @p35, @p36, @p37, @p38)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p28;
+      DELETE FROM "People"
+      WHERE "Id" = @p29;
+      DELETE FROM "People"
+      WHERE "Id" = @p30;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p31, @p32, @p33, @p34, @p35, @p36, @p37, @p38)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '5d8ec96c-5e08-48d8-8af5-20d91d1acfd0' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[<generated>_2].Owner' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Include("Owner")
+      .Count()'
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[<generated>_2].Owner' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_3 in DbSet<TodoItem>
+      select [<generated>_3])
+      .Include("Owner")
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_3 in DbSet<TodoItem> select [<generated>_3]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_3 in DbSet<TodoItem> select [<generated>_3]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[<generated>_3].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_3 in DbSet<TodoItem>
+      join Person t.Owner in DbSet<Person>
+      on Property([<generated>_3], "OwnerId") equals (Nullable<int>)Property([t.Owner], "Id") into t.Owner_group
+      from Person t.Owner in 
+          (from Person t.Owner_groupItem in [t.Owner_group]
+          select [t.Owner_groupItem]).DefaultIfEmpty()
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [<generated>_3], 
+          included: new object[]{ [t.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      ))
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _Select(
+                  source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+                          FROM "TodoItems" AS "t"
+                          LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+                          LIMIT @__p_1 OFFSET @__p_0, 
+                      shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                  selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                      queryContext: queryContext, 
+                      entity: t1.Outer, 
+                      included: new object[]{ t1.Inner }, 
+                      fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                      {
+                          Void queryContext.QueryBuffer.StartTracking(
+                              entity: entity, 
+                              entityType: EntityType: TodoItem)
+                          return !(bool ReferenceEquals(included[0], null)) ? 
+                          {
+                              Void queryContext.QueryBuffer.StartTracking(
+                                  entity: included[0], 
+                                  entityType: EntityType: Person)
+                              Void SetRelationshipSnapshotValue(
+                                  stateManager: queryContext.StateManager, 
+                                  navigation: TodoItem.Owner, 
+                                  entity: entity, 
+                                  value: included[0])
+                              return Void AddToCollectionSnapshot(
+                                  stateManager: queryContext.StateManager, 
+                                  navigation: Person.TodoItems, 
+                                  entity: included[0], 
+                                  value: entity)
+                          }
+                           : default(Void)
+                      }
+                  )), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 76.304ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 76.304ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 96.232ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 96.232ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (0ms) [Parameters=[@p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (0ms) [Parameters=[@p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '5b834c60-041f-4099-83c5-05901ad2c3a8' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Include("Owner")
+      .Count()'
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[<generated>_2].Owner' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[<generated>_2].Owner' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_3 in DbSet<TodoItem>
+      select [<generated>_3])
+      .Include("Owner")
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_3 in DbSet<TodoItem> select [<generated>_3]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_3 in DbSet<TodoItem> select [<generated>_3]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[<generated>_3].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_3 in DbSet<TodoItem>
+      join Person t.Owner in DbSet<Person>
+      on Property([<generated>_3], "OwnerId") equals (Nullable<int>)Property([t.Owner], "Id") into t.Owner_group
+      from Person t.Owner in 
+          (from Person t.Owner_groupItem in [t.Owner_group]
+          select [t.Owner_groupItem]).DefaultIfEmpty()
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [<generated>_3], 
+          included: new object[]{ [t.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      ))
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _Select(
+                  source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+                          FROM "TodoItems" AS "t"
+                          LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+                          LIMIT @__p_1 OFFSET @__p_0, 
+                      shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                  selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                      queryContext: queryContext, 
+                      entity: t1.Outer, 
+                      included: new object[]{ t1.Inner }, 
+                      fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                      {
+                          Void queryContext.QueryBuffer.StartTracking(
+                              entity: entity, 
+                              entityType: EntityType: TodoItem)
+                          return !(bool ReferenceEquals(included[0], null)) ? 
+                          {
+                              Void queryContext.QueryBuffer.StartTracking(
+                                  entity: included[0], 
+                                  entityType: EntityType: Person)
+                              Void SetRelationshipSnapshotValue(
+                                  stateManager: queryContext.StateManager, 
+                                  navigation: TodoItem.Owner, 
+                                  entity: entity, 
+                                  value: included[0])
+                              return Void AddToCollectionSnapshot(
+                                  stateManager: queryContext.StateManager, 
+                                  navigation: Person.TodoItems, 
+                                  entity: included[0], 
+                                  value: entity)
+                          }
+                           : default(Void)
+                      }
+                  )), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId", "t.Owner"."Id", "t.Owner"."FirstName", "t.Owner"."LastName"
+      FROM "TodoItems" AS "t"
+      LEFT JOIN "People" AS "t.Owner" ON "t"."OwnerId" = "t.Owner"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 80.648ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 80.648ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 100.942ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 100.942ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).First()'
+warn: Microsoft.EntityFrameworkCore.Query[10103]
+      Query: '(from Person <generated>_1 in DbSet<Person> select [<generated>_1]).First()' uses First/FirstOrDefault operation without OrderBy and filter which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10103]
+      Query: '(from Person <generated>_1 in DbSet<Person> select [<generated>_1]).First()' uses First/FirstOrDefault operation without OrderBy and filter which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).First()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<Person> _InterceptExceptions(
+          source: IEnumerable<Person> _TrackEntities(
+              results: IEnumerable<Person> _ToSequence(Person First(IEnumerable<Person> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+                              FROM "People" AS "p"
+                              LIMIT 1, 
+                          shaper: UnbufferedEntityShaper<Person>))), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/888?include=non-existent-relationship  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/888?include=non-existent-relationship  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PatchAsync (JsonApiDotNetCoreExample)' with id 'e3d89928-9c88-496c-b73a-f712ea6b3a37' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.DeleteAsync (JsonApiDotNetCoreExample)' with id '0564ca1d-138d-4994-89ff-4c633b77efa6' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments (888) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments (888) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Invalid relationship non-existent-relationship on people
+   at JsonApiDotNetCore.Data.DefaultEntityRepository`2.Include(IQueryable`1 entities, String relationshipName) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs:line 139
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<>c__DisplayClass7_0.<GetWithRelationshipsAsync>b__0(String r) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 77
+   at System.Collections.Generic.List`1.ForEach(Action`1 action)
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<GetWithRelationshipsAsync>d__7.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 75
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<GetAsync>d__5.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 63
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2.<GetAsync>d__13.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 118
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.JsonApiController`2.<GetAsync>d__4.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 65
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Invalid relationship non-existent-relationship on people
+   at JsonApiDotNetCore.Data.DefaultEntityRepository`2.Include(IQueryable`1 entities, String relationshipName) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs:line 139
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<>c__DisplayClass7_0.<GetWithRelationshipsAsync>b__0(String r) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 77
+   at System.Collections.Generic.List`1.ForEach(Action`1 action)
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<GetWithRelationshipsAsync>d__7.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 75
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Services.EntityResourceService`2.<GetAsync>d__5.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/EntityResourceService.cs:line 63
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2.<GetAsync>d__13.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 118
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
+   at JsonApiDotNetCore.Controllers.JsonApiController`2.<GetAsync>d__4.MoveNext() in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 65
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 14.734ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 14.734ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 32.884ms 400 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 32.884ms 400 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2622?include=owner  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2622?include=owner  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '2e60476c-d745-4d1d-9734-3048cf0e06f7' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '892e3c0c-6a62-4b84-bc3b-630712d4abda' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2622) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2622) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e])
+      .Include("Owner")
+      .FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[e].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      join Person e.Owner in DbSet<Person>
+      on Property([e], "OwnerId") equals (Nullable<int>)Property([e.Owner], "Id") into e.Owner_group
+      from Person e.Owner in 
+          (from Person e.Owner_groupItem in [e.Owner_group]
+          select [e.Owner_groupItem]).DefaultIfEmpty()
+      where bool [e].Id.Equals((object)__id_0)
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ [e.Owner] }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              return !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      )).FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> FirstOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _Select(
+                          source: IAsyncEnumerable<TransparentIdentifier<TodoItem, Person>> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+                                  FROM "TodoItems" AS "e"
+                                  LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+                                  WHERE "e"."Id" = @__id_0
+                                  LIMIT 1, 
+                              shaper: TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>), 
+                          selector: (TransparentIdentifier<TodoItem, Person> t1) => TodoItem _Include(
+                              queryContext: queryContext, 
+                              entity: t1.Outer, 
+                              included: new object[]{ t1.Inner }, 
+                              fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: TodoItem)
+                                  return !(bool ReferenceEquals(included[0], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[0], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Owner, 
+                                          entity: entity, 
+                                          value: included[0])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.TodoItems, 
+                                          entity: included[0], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                              }
+                          )), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 68.602ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 68.602ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 92.782ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 92.782ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/891?include=todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/891?include=todo-items  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PatchAsync (JsonApiDotNetCoreExample)' with id '422cb7bd-76e2-4921-a970-fd3b6e53cbc5' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.DeleteAsync (JsonApiDotNetCoreExample)' with id '704b8366-e2fb-4047-91ac-ef75d37aadf9' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments (891) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments (891) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person e in DbSet<Person>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e])
+      .Include("TodoItems")
+      .FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[e].TodoItems'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person e in DbSet<Person>
+      where bool [e].Id.Equals((object)__id_0)
+      order by (Nullable<int>)EF.Property(?[e]?, "Id") asc
+      select Task<Person> _IncludeAsync(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ }, 
+          fixup: (QueryContext queryContext | Person entity | Object[] included | CancellationToken ct) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: Person)
+              return Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                  includeId: 0, 
+                  navigation: Person.TodoItems, 
+                  inverseNavigation: TodoItem.Owner, 
+                  targetEntityType: EntityType: TodoItem, 
+                  clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                  inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                  tracking: True, 
+                  instance: entity, 
+                  valuesFactory: (Func<IAsyncEnumerable<object>>)() => 
+                      from TodoItem e.TodoItems in DbSet<TodoItem>
+                      join AnonymousObject _e in 
+                          (from Person e in DbSet<Person>
+                          where bool [e].Id.Equals((object)__id_0)
+                          order by (Nullable<int>)EF.Property(?[e]?, "Id") asc
+                          select new AnonymousObject(new object[]{ (object)EF.Property(?[e]?, "Id") })).Take(1)
+                      on Property([e.TodoItems], "OwnerId") equals (Nullable<int>)object [_e].GetValue(0)
+                      order by object [_e].GetValue(0) asc
+                      select [e.TodoItems], 
+                  cancellationToken: ct)
+          }
+          , 
+          cancellationToken: ct).Result).FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<Person> _InterceptExceptions(
+          source: IAsyncEnumerable<Person> _TrackEntities(
+              results: IAsyncEnumerable<Person> _ToSequence(Task<Person> FirstOrDefault(
+                      source: IAsyncEnumerable<Person> _SelectAsync(
+                          source: IAsyncEnumerable<Person> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+                                  FROM "People" AS "e"
+                                  WHERE "e"."Id" = @__id_0
+                                  ORDER BY "e"."Id"
+                                  LIMIT 1, 
+                              shaper: BufferedEntityShaper<Person>), 
+                          selector: (Person e | CancellationToken ct) => Task<Person> _ExecuteAsync(
+                              taskFactories: new Func<Task<object>>[]{ () => Task<object> _ToObjectTask(Task<Person> _IncludeAsync(
+                                          queryContext: queryContext, 
+                                          entity: e, 
+                                          included: new object[]{ }, 
+                                          fixup: (QueryContext queryContext | Person entity | Object[] included | CancellationToken ct) => 
+                                          {
+                                              Void queryContext.QueryBuffer.StartTracking(
+                                                  entity: entity, 
+                                                  entityType: EntityType: Person)
+                                              return Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                                                  includeId: 0, 
+                                                  navigation: Person.TodoItems, 
+                                                  inverseNavigation: TodoItem.Owner, 
+                                                  targetEntityType: EntityType: TodoItem, 
+                                                  clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                                                  inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                                                  tracking: True, 
+                                                  instance: entity, 
+                                                  valuesFactory: (Func<IAsyncEnumerable<object>>)() => IAsyncEnumerable<TodoItem> _ShapedQuery(
+                                                      queryContext: queryContext, 
+                                                      shaperCommandContext: SelectExpression: 
+                                                          SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+                                                          FROM "TodoItems" AS "e.TodoItems"
+                                                          INNER JOIN (
+                                                              SELECT "e0"."Id"
+                                                              FROM "People" AS "e0"
+                                                              WHERE "e0"."Id" = @__id_0
+                                                              ORDER BY "e0"."Id"
+                                                              LIMIT 1
+                                                          ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+                                                          ORDER BY "t"."Id", 
+                                                      shaper: BufferedEntityShaper<TodoItem>), 
+                                                  cancellationToken: ct)
+                                          }
+                                          , 
+                                          cancellationToken: Unhandled parameter: ct)) }, 
+                              selector: (Object[] results) => (Person)results[0])), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 121.247ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 121.247ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 140.619ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 140.619ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/888?include=owner.name  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/888?include=owner.name  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PatchAsync (JsonApiDotNetCoreExample)' with id 'b46d9cb1-c51a-434d-9ecd-e4dd6d0d699f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.DeleteAsync (JsonApiDotNetCoreExample)' with id '2deec43b-6907-4519-a36a-21a2dbd0b0f6' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Deeply nested relationships are not supported
+   at JsonApiDotNetCore.Services.QueryParser.ParseIncludedRelationships(String value) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 176
+   at JsonApiDotNetCore.Services.QueryParser.Parse(IQueryCollection query) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 57
+   at JsonApiDotNetCore.Services.JsonApiContext.ApplyContext[T](Object controller) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/JsonApiContext.cs:line 70
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 56
+   at JsonApiDotNetCore.Controllers.JsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 40
+   at JsonApiDotNetCore.Controllers.JsonApiController`1..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 17
+   at JsonApiDotNetCoreExample.Controllers.PeopleController..ctor(IJsonApiContext jsonApiContext, IResourceService`1 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/Examples/JsonApiDotNetCoreExample/Controllers/PeopleController.cs:line 14
+   at lambda_method(Closure , IServiceProvider , Object[] )
+   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+fail: JsonApiDotNetCore.Middleware.JsonApiExceptionFilter[0]
+      An unhandled exception occurred during the request
+JsonApiDotNetCore.Internal.JsonApiException: Deeply nested relationships are not supported
+   at JsonApiDotNetCore.Services.QueryParser.ParseIncludedRelationships(String value) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 176
+   at JsonApiDotNetCore.Services.QueryParser.Parse(IQueryCollection query) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/QueryParser.cs:line 57
+   at JsonApiDotNetCore.Services.JsonApiContext.ApplyContext[T](Object controller) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Services/JsonApiContext.cs:line 70
+   at JsonApiDotNetCore.Controllers.BaseJsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 56
+   at JsonApiDotNetCore.Controllers.JsonApiController`2..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 40
+   at JsonApiDotNetCore.Controllers.JsonApiController`1..ctor(IJsonApiContext jsonApiContext, IResourceService`2 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 17
+   at JsonApiDotNetCoreExample.Controllers.PeopleController..ctor(IJsonApiContext jsonApiContext, IResourceService`1 resourceService, ILoggerFactory loggerFactory) in /Users/jarednance/dev/json-api-dotnet-core/src/Examples/JsonApiDotNetCoreExample/Controllers/PeopleController.cs:line 14
+   at lambda_method(Closure , IServiceProvider , Object[] )
+   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
+   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
+--- End of stack trace from previous location where exception was thrown ---
+   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
+   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
+   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 5.157ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 5.157ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 25.495ms 400 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 25.495ms 400 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItemCollections" ("Id", "Name", "OwnerId")
+      VALUES (@p2, @p3, @p4);
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItemCollections" ("Id", "Name", "OwnerId")
+      VALUES (@p2, @p3, @p4);
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItemCollections" ("Id", "Name", "OwnerId")
+      VALUES (@p2, @p3, @p4);
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/892?include=todo-items,todo-collections  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/892?include=todo-items,todo-collections  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PatchAsync (JsonApiDotNetCoreExample)' with id '3f6bab1b-ca52-4fbd-a8c4-dee3c0df1851' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.DeleteAsync (JsonApiDotNetCoreExample)' with id '0c5a6576-2492-4aff-80c7-4f36a82e8d14' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments (892) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments (892) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person e in DbSet<Person>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e])
+      .Include("TodoItems")
+      .Include("TodoItemCollections")
+      .FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[e].TodoItems'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[e].TodoItemCollections'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person e in DbSet<Person>
+      where bool [e].Id.Equals((object)__id_0)
+      order by (Nullable<int>)EF.Property(?[e]?, "Id") asc
+      select Task<Person> _IncludeAsync(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]{ }, 
+          fixup: (QueryContext queryContext | Person entity | Object[] included | CancellationToken ct) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: Person)
+              return Task _AwaitMany(new Func<Task>[]
+                  { 
+                      () => Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                          includeId: 0, 
+                          navigation: Person.TodoItems, 
+                          inverseNavigation: TodoItem.Owner, 
+                          targetEntityType: EntityType: TodoItem, 
+                          clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                          inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                          tracking: True, 
+                          instance: entity, 
+                          valuesFactory: (Func<IAsyncEnumerable<object>>)() => 
+                              from TodoItem e.TodoItems in DbSet<TodoItem>
+                              join AnonymousObject _e in 
+                                  (from Person e in DbSet<Person>
+                                  where bool [e].Id.Equals((object)__id_0)
+                                  order by (Nullable<int>)EF.Property(?[e]?, "Id") asc
+                                  select new AnonymousObject(new object[]{ (object)EF.Property(?[e]?, "Id") })).Take(1)
+                              on Property([e.TodoItems], "OwnerId") equals (Nullable<int>)object [_e].GetValue(0)
+                              order by object [_e].GetValue(0) asc
+                              select [e.TodoItems], 
+                          cancellationToken: ct), 
+                      () => Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                          includeId: 1, 
+                          navigation: Person.TodoItemCollections, 
+                          inverseNavigation: TodoItemCollection.Owner, 
+                          targetEntityType: EntityType: TodoItemCollection, 
+                          clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItemCollection>, TodoItemCollection>, 
+                          inverseClrPropertySetter: ClrPropertySetter<TodoItemCollection, Person>, 
+                          tracking: True, 
+                          instance: entity, 
+                          valuesFactory: (Func<IAsyncEnumerable<object>>)() => 
+                              from TodoItemCollection e.TodoItemCollections in DbSet<TodoItemCollection>
+                              join AnonymousObject _e in 
+                                  (from Person e in DbSet<Person>
+                                  where bool [e].Id.Equals((object)__id_0)
+                                  order by (Nullable<int>)EF.Property(?[e]?, "Id") asc
+                                  select new AnonymousObject(new object[]{ (object)EF.Property(?[e]?, "Id") })).Take(1)
+                              on Property([e.TodoItemCollections], "OwnerId") equals (Nullable<int>)object [_e].GetValue(0)
+                              order by object [_e].GetValue(0) asc
+                              select [e.TodoItemCollections], 
+                          cancellationToken: ct) 
+                  })
+          }
+          , 
+          cancellationToken: ct).Result).FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<Person> _InterceptExceptions(
+          source: IAsyncEnumerable<Person> _TrackEntities(
+              results: IAsyncEnumerable<Person> _ToSequence(Task<Person> FirstOrDefault(
+                      source: IAsyncEnumerable<Person> _SelectAsync(
+                          source: IAsyncEnumerable<Person> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+                                  FROM "People" AS "e"
+                                  WHERE "e"."Id" = @__id_0
+                                  ORDER BY "e"."Id"
+                                  LIMIT 1, 
+                              shaper: BufferedEntityShaper<Person>), 
+                          selector: (Person e | CancellationToken ct) => Task<Person> _ExecuteAsync(
+                              taskFactories: new Func<Task<object>>[]{ () => Task<object> _ToObjectTask(Task<Person> _IncludeAsync(
+                                          queryContext: queryContext, 
+                                          entity: e, 
+                                          included: new object[]{ }, 
+                                          fixup: (QueryContext queryContext | Person entity | Object[] included | CancellationToken ct) => 
+                                          {
+                                              Void queryContext.QueryBuffer.StartTracking(
+                                                  entity: entity, 
+                                                  entityType: EntityType: Person)
+                                              return Task _AwaitMany(new Func<Task>[]
+                                                  { 
+                                                      () => Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                                                          includeId: 0, 
+                                                          navigation: Person.TodoItems, 
+                                                          inverseNavigation: TodoItem.Owner, 
+                                                          targetEntityType: EntityType: TodoItem, 
+                                                          clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                                                          inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                                                          tracking: True, 
+                                                          instance: entity, 
+                                                          valuesFactory: (Func<IAsyncEnumerable<object>>)() => IAsyncEnumerable<TodoItem> _ShapedQuery(
+                                                              queryContext: queryContext, 
+                                                              shaperCommandContext: SelectExpression: 
+                                                                  SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+                                                                  FROM "TodoItems" AS "e.TodoItems"
+                                                                  INNER JOIN (
+                                                                      SELECT "e0"."Id"
+                                                                      FROM "People" AS "e0"
+                                                                      WHERE "e0"."Id" = @__id_0
+                                                                      ORDER BY "e0"."Id"
+                                                                      LIMIT 1
+                                                                  ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+                                                                  ORDER BY "t"."Id", 
+                                                              shaper: BufferedEntityShaper<TodoItem>), 
+                                                          cancellationToken: ct), 
+                                                      () => Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                                                          includeId: 1, 
+                                                          navigation: Person.TodoItemCollections, 
+                                                          inverseNavigation: TodoItemCollection.Owner, 
+                                                          targetEntityType: EntityType: TodoItemCollection, 
+                                                          clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItemCollection>, TodoItemCollection>, 
+                                                          inverseClrPropertySetter: ClrPropertySetter<TodoItemCollection, Person>, 
+                                                          tracking: True, 
+                                                          instance: entity, 
+                                                          valuesFactory: (Func<IAsyncEnumerable<object>>)() => IAsyncEnumerable<TodoItemCollection> _ShapedQuery(
+                                                              queryContext: queryContext, 
+                                                              shaperCommandContext: SelectExpression: 
+                                                                  SELECT "e.TodoItemCollections"."Id", "e.TodoItemCollections"."Name", "e.TodoItemCollections"."OwnerId"
+                                                                  FROM "TodoItemCollections" AS "e.TodoItemCollections"
+                                                                  INNER JOIN (
+                                                                      SELECT "e1"."Id"
+                                                                      FROM "People" AS "e1"
+                                                                      WHERE "e1"."Id" = @__id_0
+                                                                      ORDER BY "e1"."Id"
+                                                                      LIMIT 1
+                                                                  ) AS "t0" ON "e.TodoItemCollections"."OwnerId" = "t0"."Id"
+                                                                  ORDER BY "t0"."Id", 
+                                                              shaper: BufferedEntityShaper<TodoItemCollection>), 
+                                                          cancellationToken: ct) 
+                                                  })
+                                          }
+                                          , 
+                                          cancellationToken: Unhandled parameter: ct)) }, 
+                              selector: (Object[] results) => (Person)results[0])), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      ORDER BY "e"."Id"
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItems"."Id", "e.TodoItems"."AchievedDate", "e.TodoItems"."AssigneeId", "e.TodoItems"."CollectionId", "e.TodoItems"."CreatedDate", "e.TodoItems"."Description", "e.TodoItems"."GuidProperty", "e.TodoItems"."Ordinal", "e.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "e.TodoItems"
+      INNER JOIN (
+          SELECT "e0"."Id"
+          FROM "People" AS "e0"
+          WHERE "e0"."Id" = @__id_0
+          ORDER BY "e0"."Id"
+          LIMIT 1
+      ) AS "t" ON "e.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItemCollections"."Id", "e.TodoItemCollections"."Name", "e.TodoItemCollections"."OwnerId"
+      FROM "TodoItemCollections" AS "e.TodoItemCollections"
+      INNER JOIN (
+          SELECT "e1"."Id"
+          FROM "People" AS "e1"
+          WHERE "e1"."Id" = @__id_0
+          ORDER BY "e1"."Id"
+          LIMIT 1
+      ) AS "t0" ON "e.TodoItemCollections"."OwnerId" = "t0"."Id"
+      ORDER BY "t0"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItemCollections"."Id", "e.TodoItemCollections"."Name", "e.TodoItemCollections"."OwnerId"
+      FROM "TodoItemCollections" AS "e.TodoItemCollections"
+      INNER JOIN (
+          SELECT "e1"."Id"
+          FROM "People" AS "e1"
+          WHERE "e1"."Id" = @__id_0
+          ORDER BY "e1"."Id"
+          LIMIT 1
+      ) AS "t0" ON "e.TodoItemCollections"."OwnerId" = "t0"."Id"
+      ORDER BY "t0"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e.TodoItemCollections"."Id", "e.TodoItemCollections"."Name", "e.TodoItemCollections"."OwnerId"
+      FROM "TodoItemCollections" AS "e.TodoItemCollections"
+      INNER JOIN (
+          SELECT "e1"."Id"
+          FROM "People" AS "e1"
+          WHERE "e1"."Id" = @__id_0
+          ORDER BY "e1"."Id"
+          LIMIT 1
+      ) AS "t0" ON "e.TodoItemCollections"."OwnerId" = "t0"."Id"
+      ORDER BY "t0"."Id"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 129.696ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 129.696ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 149.864ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 149.864ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p0;
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p1, @p2)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p0;
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p1, @p2)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p0;
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p1, @p2)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p15;
+      DELETE FROM "People"
+      WHERE "Id" = @p16;
+      DELETE FROM "People"
+      WHERE "Id" = @p17;
+      DELETE FROM "People"
+      WHERE "Id" = @p18;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p15;
+      DELETE FROM "People"
+      WHERE "Id" = @p16;
+      DELETE FROM "People"
+      WHERE "Id" = @p17;
+      DELETE FROM "People"
+      WHERE "Id" = @p18;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p15;
+      DELETE FROM "People"
+      WHERE "Id" = @p16;
+      DELETE FROM "People"
+      WHERE "Id" = @p17;
+      DELETE FROM "People"
+      WHERE "Id" = @p18;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2633?include=owner&include=assignee  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2633?include=owner&include=assignee  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '49eb2ce9-b9a4-4b60-8f0d-9dc16928dad7' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '0d5cc266-1ec4-468a-84c2-4323d7e9b49c' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2633) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e])
+      .Include("Owner")
+      .Include("Assignee")
+      .FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[e].Owner'
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[e].Assignee'
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2633) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      join Person e.Assignee in DbSet<Person>
+      on Property([e], "AssigneeId") equals (Nullable<int>)Property([e.Assignee], "Id") into e.Assignee_group
+      from Person e.Assignee in 
+          (from Person e.Assignee_groupItem in [e.Assignee_group]
+          select [e.Assignee_groupItem]).DefaultIfEmpty()
+      join Person e.Owner in DbSet<Person>
+      on Property([e], "OwnerId") equals (Nullable<int>)Property([e.Owner], "Id") into e.Owner_group
+      from Person e.Owner in 
+          (from Person e.Owner_groupItem in [e.Owner_group]
+          select [e.Owner_groupItem]).DefaultIfEmpty()
+      where bool [e].Id.Equals((object)__id_0)
+      select TodoItem _Include(
+          queryContext: queryContext, 
+          entity: [e], 
+          included: new object[]
+          { 
+              [e.Owner], 
+              [e.Assignee] 
+          }, 
+          fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: TodoItem)
+              !(bool ReferenceEquals(included[0], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[0], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Owner, 
+                      entity: entity, 
+                      value: included[0])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.TodoItems, 
+                      entity: included[0], 
+                      value: entity)
+              }
+               : default(Void)
+              return !(bool ReferenceEquals(included[1], null)) ? 
+              {
+                  Void queryContext.QueryBuffer.StartTracking(
+                      entity: included[1], 
+                      entityType: EntityType: Person)
+                  Void SetRelationshipSnapshotValue(
+                      stateManager: queryContext.StateManager, 
+                      navigation: TodoItem.Assignee, 
+                      entity: entity, 
+                      value: included[1])
+                  return Void AddToCollectionSnapshot(
+                      stateManager: queryContext.StateManager, 
+                      navigation: Person.AssignedTodoItems, 
+                      entity: included[1], 
+                      value: entity)
+              }
+               : default(Void)
+          }
+      )).FirstOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> FirstOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _Select(
+                          source: IAsyncEnumerable<TransparentIdentifier<TransparentIdentifier<TodoItem, Person>, Person>> _ShapedQuery(
+                              queryContext: queryContext, 
+                              shaperCommandContext: SelectExpression: 
+                                  SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Assignee"."Id", "e.Assignee"."FirstName", "e.Assignee"."LastName", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+                                  FROM "TodoItems" AS "e"
+                                  LEFT JOIN "People" AS "e.Assignee" ON "e"."AssigneeId" = "e.Assignee"."Id"
+                                  LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+                                  WHERE "e"."Id" = @__id_0
+                                  LIMIT 1, 
+                              shaper: TypedCompositeShaper<TypedCompositeShaper<BufferedOffsetEntityShaper<TodoItem>, TodoItem, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TodoItem, Person>>, TransparentIdentifier<TodoItem, Person>, BufferedOffsetEntityShaper<Person>, Person, TransparentIdentifier<TransparentIdentifier<TodoItem, Person>, Person>>), 
+                          selector: (TransparentIdentifier<TransparentIdentifier<TodoItem, Person>, Person> t3) => TodoItem _Include(
+                              queryContext: queryContext, 
+                              entity: t3.Outer.Outer, 
+                              included: new object[]
+                              { 
+                                  t3.Inner, 
+                                  t3.Outer.Inner 
+                              }, 
+                              fixup: (QueryContext queryContext | TodoItem entity | Object[] included) => 
+                              {
+                                  Void queryContext.QueryBuffer.StartTracking(
+                                      entity: entity, 
+                                      entityType: EntityType: TodoItem)
+                                  !(bool ReferenceEquals(included[0], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[0], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Owner, 
+                                          entity: entity, 
+                                          value: included[0])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.TodoItems, 
+                                          entity: included[0], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                                  return !(bool ReferenceEquals(included[1], null)) ? 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: included[1], 
+                                          entityType: EntityType: Person)
+                                      Void SetRelationshipSnapshotValue(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: TodoItem.Assignee, 
+                                          entity: entity, 
+                                          value: included[1])
+                                      return Void AddToCollectionSnapshot(
+                                          stateManager: queryContext.StateManager, 
+                                          navigation: Person.AssignedTodoItems, 
+                                          entity: included[1], 
+                                          value: entity)
+                                  }
+                                   : default(Void)
+                              }
+                          )), 
+                      cancellationToken: Unhandled parameter: queryContext.CancellationToken)), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Assignee"."Id", "e.Assignee"."FirstName", "e.Assignee"."LastName", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Assignee" ON "e"."AssigneeId" = "e.Assignee"."Id"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (15ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Assignee"."Id", "e.Assignee"."FirstName", "e.Assignee"."LastName", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Assignee" ON "e"."AssigneeId" = "e.Assignee"."Id"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (15ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId", "e.Assignee"."Id", "e.Assignee"."FirstName", "e.Assignee"."LastName", "e.Owner"."Id", "e.Owner"."FirstName", "e.Owner"."LastName"
+      FROM "TodoItems" AS "e"
+      LEFT JOIN "People" AS "e.Assignee" ON "e"."AssigneeId" = "e.Assignee"."Id"
+      LEFT JOIN "People" AS "e.Owner" ON "e"."OwnerId" = "e.Owner"."Id"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 1
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 111.286ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 111.286ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 131.712ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 131.712ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p3;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p3;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "People"
+      WHERE "Id" = @p3;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people?include=todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people?include=todo-items  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PostAsync (JsonApiDotNetCoreExample)' with id '1eaf2dd2-1dd5-46db-ba6f-88148a37f5ec' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_2 in DbSet<Person>
+      select [<generated>_2])
+      .Include("TodoItems")
+      .Count()'
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[<generated>_2].TodoItems' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_2 in DbSet<Person>
+      select [<generated>_2]).Count()'
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[<generated>_2].TodoItems' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "People" AS "p"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_3 in DbSet<Person>
+      select [<generated>_3])
+      .Include("TodoItems")
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from Person <generated>_3 in DbSet<Person> select [<generated>_3]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from Person <generated>_3 in DbSet<Person> select [<generated>_3]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10105]
+      Including navigation: '[<generated>_3].TodoItems'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_3 in DbSet<Person>
+      order by (Nullable<int>)EF.Property(?[<generated>_3]?, "Id") asc
+      select Task<Person> _IncludeAsync(
+          queryContext: queryContext, 
+          entity: [<generated>_3], 
+          included: new object[]{ }, 
+          fixup: (QueryContext queryContext | Person entity | Object[] included | CancellationToken ct) => 
+          {
+              Void queryContext.QueryBuffer.StartTracking(
+                  entity: entity, 
+                  entityType: EntityType: Person)
+              return Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                  includeId: 0, 
+                  navigation: Person.TodoItems, 
+                  inverseNavigation: TodoItem.Owner, 
+                  targetEntityType: EntityType: TodoItem, 
+                  clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                  inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                  tracking: True, 
+                  instance: entity, 
+                  valuesFactory: (Func<IAsyncEnumerable<object>>)() => 
+                      from TodoItem p.TodoItems in DbSet<TodoItem>
+                      join AnonymousObject _<generated>_3 in 
+                          (from Person <generated>_3 in DbSet<Person>
+                          order by (Nullable<int>)EF.Property(?[<generated>_3]?, "Id") asc
+                          select new AnonymousObject(new object[]{ (object)EF.Property(?[<generated>_3]?, "Id") }))
+                          .Skip(__p_0)
+                          .Take(__p_1)
+                      on Property([p.TodoItems], "OwnerId") equals (Nullable<int>)object [_<generated>_3].GetValue(0)
+                      order by object [_<generated>_3].GetValue(0) asc
+                      select [p.TodoItems], 
+                  cancellationToken: ct)
+          }
+          , 
+          cancellationToken: ct).Result)
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<Person> _InterceptExceptions(
+          source: IAsyncEnumerable<Person> _TrackEntities(
+              results: IAsyncEnumerable<Person> _SelectAsync(
+                  source: IAsyncEnumerable<Person> _ShapedQuery(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+                          FROM "People" AS "p"
+                          ORDER BY "p"."Id"
+                          LIMIT @__p_1 OFFSET @__p_0, 
+                      shaper: BufferedEntityShaper<Person>), 
+                  selector: (Person <generated>_3 | CancellationToken ct) => Task<Person> _ExecuteAsync(
+                      taskFactories: new Func<Task<object>>[]{ () => Task<object> _ToObjectTask(Task<Person> _IncludeAsync(
+                                  queryContext: queryContext, 
+                                  entity: <generated>_3, 
+                                  included: new object[]{ }, 
+                                  fixup: (QueryContext queryContext | Person entity | Object[] included | CancellationToken ct) => 
+                                  {
+                                      Void queryContext.QueryBuffer.StartTracking(
+                                          entity: entity, 
+                                          entityType: EntityType: Person)
+                                      return Task queryContext.QueryBuffer.IncludeCollectionAsync(
+                                          includeId: 0, 
+                                          navigation: Person.TodoItems, 
+                                          inverseNavigation: TodoItem.Owner, 
+                                          targetEntityType: EntityType: TodoItem, 
+                                          clrCollectionAccessor: ClrICollectionAccessor<Person, List<TodoItem>, TodoItem>, 
+                                          inverseClrPropertySetter: ClrPropertySetter<TodoItem, Person>, 
+                                          tracking: True, 
+                                          instance: entity, 
+                                          valuesFactory: (Func<IAsyncEnumerable<object>>)() => IAsyncEnumerable<TodoItem> _ShapedQuery(
+                                              queryContext: queryContext, 
+                                              shaperCommandContext: SelectExpression: 
+                                                  SELECT "p.TodoItems"."Id", "p.TodoItems"."AchievedDate", "p.TodoItems"."AssigneeId", "p.TodoItems"."CollectionId", "p.TodoItems"."CreatedDate", "p.TodoItems"."Description", "p.TodoItems"."GuidProperty", "p.TodoItems"."Ordinal", "p.TodoItems"."OwnerId"
+                                                  FROM "TodoItems" AS "p.TodoItems"
+                                                  INNER JOIN (
+                                                      SELECT "p0"."Id"
+                                                      FROM "People" AS "p0"
+                                                      ORDER BY "p0"."Id"
+                                                      LIMIT @__p_1 OFFSET @__p_0
+                                                  ) AS "t" ON "p.TodoItems"."OwnerId" = "t"."Id"
+                                                  ORDER BY "t"."Id", 
+                                              shaper: BufferedEntityShaper<TodoItem>), 
+                                          cancellationToken: ct)
+                                  }
+                                  , 
+                                  cancellationToken: Unhandled parameter: ct)) }, 
+                      selector: (Object[] results) => (Person)results[0])), 
+              queryContext: Unhandled parameter: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: Unhandled parameter: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      ORDER BY "p"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      ORDER BY "p"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      ORDER BY "p"."Id"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p.TodoItems"."Id", "p.TodoItems"."AchievedDate", "p.TodoItems"."AssigneeId", "p.TodoItems"."CollectionId", "p.TodoItems"."CreatedDate", "p.TodoItems"."Description", "p.TodoItems"."GuidProperty", "p.TodoItems"."Ordinal", "p.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "p.TodoItems"
+      INNER JOIN (
+          SELECT "p0"."Id"
+          FROM "People" AS "p0"
+          ORDER BY "p0"."Id"
+          LIMIT @__p_1 OFFSET @__p_0
+      ) AS "t" ON "p.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p.TodoItems"."Id", "p.TodoItems"."AchievedDate", "p.TodoItems"."AssigneeId", "p.TodoItems"."CollectionId", "p.TodoItems"."CreatedDate", "p.TodoItems"."Description", "p.TodoItems"."GuidProperty", "p.TodoItems"."Ordinal", "p.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "p.TodoItems"
+      INNER JOIN (
+          SELECT "p0"."Id"
+          FROM "People" AS "p0"
+          ORDER BY "p0"."Id"
+          LIMIT @__p_1 OFFSET @__p_0
+      ) AS "t" ON "p.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p.TodoItems"."Id", "p.TodoItems"."AchievedDate", "p.TodoItems"."AssigneeId", "p.TodoItems"."CollectionId", "p.TodoItems"."CreatedDate", "p.TodoItems"."Description", "p.TodoItems"."GuidProperty", "p.TodoItems"."Ordinal", "p.TodoItems"."OwnerId"
+      FROM "TodoItems" AS "p.TodoItems"
+      INNER JOIN (
+          SELECT "p0"."Id"
+          FROM "People" AS "p0"
+          ORDER BY "p0"."Id"
+          LIMIT @__p_1 OFFSET @__p_0
+      ) AS "t" ON "p.TodoItems"."OwnerId" = "t"."Id"
+      ORDER BY "t"."Id"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 91.629ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 91.629ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 111.506ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 111.506ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PostAsync (JsonApiDotNetCoreExample)' with id '101783b6-922d-478e-91c4-973fb0212ed5' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "People" AS "p"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (26ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (26ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_2 in DbSet<Person>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from Person <generated>_2 in DbSet<Person> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from Person <generated>_2 in DbSet<Person> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_2 in DbSet<Person>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<Person> _InterceptExceptions(
+          source: IAsyncEnumerable<Person> _TrackEntities(
+              results: IAsyncEnumerable<Person> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+                      FROM "People" AS "p"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<Person>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 76.867ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 76.867ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 97.983ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 97.983ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id", "CreatedDate";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExampleTests
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '66278d25-d1b4-4a31-8edc-371fd1e02b91' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (9ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 51.071ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 51.071ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 73.957ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 73.957ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?', @p67='?', @p68='?', @p69='?', @p70='?', @p71='?', @p72='?', @p73='?', @p74='?', @p75='?', @p76='?', @p77='?', @p78='?', @p79='?', @p80='?', @p81='?', @p82='?', @p83='?', @p84='?', @p85='?', @p86='?', @p87='?', @p88='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p25, @p26, @p27, @p28, @p29, @p30, @p31, @p32)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p33, @p34, @p35, @p36, @p37, @p38, @p39, @p40)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p41, @p42, @p43, @p44, @p45, @p46, @p47, @p48)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p49, @p50, @p51, @p52, @p53, @p54, @p55, @p56)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p57, @p58, @p59, @p60, @p61, @p62, @p63, @p64)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p65, @p66, @p67, @p68, @p69, @p70, @p71, @p72)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p73, @p74, @p75, @p76, @p77, @p78, @p79, @p80)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p81, @p82, @p83, @p84, @p85, @p86, @p87, @p88)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?', @p67='?', @p68='?', @p69='?', @p70='?', @p71='?', @p72='?', @p73='?', @p74='?', @p75='?', @p76='?', @p77='?', @p78='?', @p79='?', @p80='?', @p81='?', @p82='?', @p83='?', @p84='?', @p85='?', @p86='?', @p87='?', @p88='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p25, @p26, @p27, @p28, @p29, @p30, @p31, @p32)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p33, @p34, @p35, @p36, @p37, @p38, @p39, @p40)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p41, @p42, @p43, @p44, @p45, @p46, @p47, @p48)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p49, @p50, @p51, @p52, @p53, @p54, @p55, @p56)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p57, @p58, @p59, @p60, @p61, @p62, @p63, @p64)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p65, @p66, @p67, @p68, @p69, @p70, @p71, @p72)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p73, @p74, @p75, @p76, @p77, @p78, @p79, @p80)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p81, @p82, @p83, @p84, @p85, @p86, @p87, @p88)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?', @p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?', @p67='?', @p68='?', @p69='?', @p70='?', @p71='?', @p72='?', @p73='?', @p74='?', @p75='?', @p76='?', @p77='?', @p78='?', @p79='?', @p80='?', @p81='?', @p82='?', @p83='?', @p84='?', @p85='?', @p86='?', @p87='?', @p88='?'], CommandType='Text', CommandTimeout='30']
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p0;
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p25, @p26, @p27, @p28, @p29, @p30, @p31, @p32)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p33, @p34, @p35, @p36, @p37, @p38, @p39, @p40)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p41, @p42, @p43, @p44, @p45, @p46, @p47, @p48)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p49, @p50, @p51, @p52, @p53, @p54, @p55, @p56)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p57, @p58, @p59, @p60, @p61, @p62, @p63, @p64)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p65, @p66, @p67, @p68, @p69, @p70, @p71, @p72)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p73, @p74, @p75, @p76, @p77, @p78, @p79, @p80)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p81, @p82, @p83, @p84, @p85, @p86, @p87, @p88)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?page[number]=2  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?page[number]=2  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '29149bf5-e575-4822-ae33-beb5fce2ffc6' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 2 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 51.095ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 70.672ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 51.095ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 70.672ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).Last()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).Last()'
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'Last()' could not be translated and will be evaluated locally.
+warn: Microsoft.EntityFrameworkCore.Query[20500]
+      The LINQ expression 'Last()' could not be translated and will be evaluated locally.
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<Person> _InterceptExceptions(
+          source: IEnumerable<Person> _TrackEntities(
+              results: IEnumerable<Person> _ToSequence(Person Last(IEnumerable<Person> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+                              FROM "People" AS "p", 
+                          shaper: UnbufferedEntityShaper<Person>))), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/894  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people/894  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PatchAsync (JsonApiDotNetCoreExample)' with id '1d8d8ad3-300b-4985-9917-0527d2f32c84' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.DeleteAsync (JsonApiDotNetCoreExample)' with id '110246c9-516c-4d15-b9ac-04e6d266b51b' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments (894) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments (894) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person e in DbSet<Person>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person e in DbSet<Person>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<Person> _InterceptExceptions(
+          source: IAsyncEnumerable<Person> _TrackEntities(
+              results: IAsyncEnumerable<Person> _ToSequence(Task<Person> SingleOrDefault(
+                      source: IAsyncEnumerable<Person> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+                              FROM "People" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<Person>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."FirstName", "e"."LastName"
+      FROM "People" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 51.526ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 72.584ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 51.526ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 72.584ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2647  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2647  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '5aeb7733-aac0-4b6a-a5b0-622a10aef310' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '3b020693-8812-48be-bf1b-028a704a3f50' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2647) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2647) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+                              FROM "TodoItems" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<TodoItem>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 43.935ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 43.935ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 66.007ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 66.007ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PostAsync (JsonApiDotNetCoreExample)' with id '53236a0e-5a42-4405-8697-b363307b0742' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "People" AS "p"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_2 in DbSet<Person>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from Person <generated>_2 in DbSet<Person> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from Person <generated>_2 in DbSet<Person> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_2 in DbSet<Person>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<Person> _InterceptExceptions(
+          source: IAsyncEnumerable<Person> _TrackEntities(
+              results: IAsyncEnumerable<Person> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+                      FROM "People" AS "p"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<Person>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 53.752ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 53.752ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 75.703ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 75.703ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2648  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2648  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id 'bc9f4094-da3f-4b54-a4b5-746a2be25e55' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '61e99f52-a4c3-40bd-92cc-955e50e086d9' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2648) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2648) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+                              FROM "TodoItems" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<TodoItem>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 43.28ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 43.28ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 67.828ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 67.828ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/custom/route/todo-items/2649  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/custom/route/todo-items/2649  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'custom/route/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.PatchAsync (JsonApiDotNetCoreExample)' with id '81b735cc-1698-4dd5-a086-6eda734699c0' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.DeleteAsync (JsonApiDotNetCoreExample)' with id '2d84b987-9823-450c-982d-b63abe1024f7' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) with arguments (2649) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) with arguments (2649) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+                              FROM "TodoItems" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<TodoItem>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) in 39.12ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) in 39.12ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 60.789ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 60.789ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/testValues  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/testValues  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'TestValues'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TestValuesController.Get (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TestValuesController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TestValuesController.Get (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TestValuesController.Get (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: JsonApiDotNetCore.Serialization.JsonApiSerializer[0]
+      Response was not a JSONAPI entity. Serializing as plain JSON.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TestValuesController.Get (JsonApiDotNetCoreExample) in 1.407ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 32.217ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TestValuesController.Get (JsonApiDotNetCoreExample) in 1.407ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 32.217ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (6ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (6ms) [Parameters=[@p0='?', @p1='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/custom/route/todo-items/2650  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/custom/route/todo-items/2650  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'custom/route/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.PatchAsync (JsonApiDotNetCoreExample)' with id '49ee8a92-89ed-4f38-906c-31ab8083271c' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.DeleteAsync (JsonApiDotNetCoreExample)' with id '744dcbe5-efca-479f-bb8f-d7e1c104d561' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) with arguments (2650) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem e in DbSet<TodoItem>
+      where bool [e].Id.Equals((object)__id_0)
+      select [e]).SingleOrDefault()'
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) with arguments (2650) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ToSequence(Task<TodoItem> SingleOrDefault(
+                      source: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                          queryContext: queryContext, 
+                          shaperCommandContext: SelectExpression: 
+                              SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+                              FROM "TodoItems" AS "e"
+                              WHERE "e"."Id" = @__id_0
+                              LIMIT 2, 
+                          shaper: UnbufferedEntityShaper<TodoItem>), 
+                      cancellationToken: queryContext.CancellationToken)), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) in 43.411ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) in 43.411ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 65.45ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 65.45ms 200 application/vnd.api+json
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/custom/route/todo-items  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/custom/route/todo-items  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'custom/route/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.PostAsync (JsonApiDotNetCoreExample)' with id '38524268-32e2-49e7-872f-c4f51a0ad8cc' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) in 54.945ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsCustomController.GetAsync (JsonApiDotNetCoreExample) in 54.945ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 69.838ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 69.838ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2651?omitNullValuedAttributes=true  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2651?omitNullValuedAttributes=true  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2651) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2651) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.765ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.765ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 3.533ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 3.533ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2652?omitNullValuedAttributes=false  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2652?omitNullValuedAttributes=false  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2652) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2652) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 3.109ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 3.109ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 3.54ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 3.54ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2653  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2653  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2653) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2653) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.247ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.247ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.645ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.645ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2654  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2654  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2654) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2654) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 3.771ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 3.771ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 4.491ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 4.491ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2655?omitNullValuedAttributes=  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2655?omitNullValuedAttributes=  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2655) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2655) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.271ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.271ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.444ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.444ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2656?omitNullValuedAttributes=false  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2656?omitNullValuedAttributes=false  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2656) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2656) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 7.526ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 7.526ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 7.947ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 7.947ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2657?omitNullValuedAttributes=true  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2657?omitNullValuedAttributes=true  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2657) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2657) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.605ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.605ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.794ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.794ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2658?omitNullValuedAttributes=true  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2658?omitNullValuedAttributes=true  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2658) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2658) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.479ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.479ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.849ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.849ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2659?omitNullValuedAttributes=foo  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2659?omitNullValuedAttributes=foo  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2659) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2659) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.266ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.266ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.441ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.441ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2660?omitNullValuedAttributes=foo  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2660?omitNullValuedAttributes=foo  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2660) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2660) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.248ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.248ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 3.239ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 3.239ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2661?omitNullValuedAttributes=foo  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2661?omitNullValuedAttributes=foo  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2661) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2661) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.492ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.683ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.492ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.683ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2662?omitNullValuedAttributes=false  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2662?omitNullValuedAttributes=false  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2662) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2662) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.181ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.181ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.539ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.539ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2663?omitNullValuedAttributes=true  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2663?omitNullValuedAttributes=true  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2663) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2663) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.411ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.411ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.782ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.782ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (5ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2664?omitNullValuedAttributes=false  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2664?omitNullValuedAttributes=false  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2664) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2664) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.755ms
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.951ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.755ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.951ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2665?omitNullValuedAttributes=foo  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2665?omitNullValuedAttributes=foo  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2665) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2665) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.481ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.481ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.66ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 2.66ms 200 application/vnd.api+json
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2666?omitNullValuedAttributes=  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items/2666?omitNullValuedAttributes=  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items/{id}'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PatchAsync (JsonApiDotNetCoreExample)' with id '1ee61db8-daf4-41f3-90d2-1cf3db87d448' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.DeleteAsync (JsonApiDotNetCoreExample)' with id '75ab2821-99d0-4a3f-9dbb-3747ee7b296e' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2666) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments (2666) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "e"."Id", "e"."AchievedDate", "e"."AssigneeId", "e"."CollectionId", "e"."CreatedDate", "e"."Description", "e"."GuidProperty", "e"."Ordinal", "e"."OwnerId"
+      FROM "TodoItems" AS "e"
+      WHERE "e"."Id" = @__id_0
+      LIMIT 2
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.802ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 2.802ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 3.245ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 3.245ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p2, @p3, @p4, @p5, @p6, @p7, @p8)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p9, @p10, @p11, @p12, @p13, @p14, @p15)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p9, @p10, @p11, @p12, @p13, @p14, @p15)
+      RETURNING "Id", "CreatedDate";
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?include=owner  
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[todoItem].Owner' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+warn: Microsoft.EntityFrameworkCore.Query[10106]
+      The Include operation for navigation '[todoItem].Owner' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@___authService_CurrentUserId_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "todoItem"
+      WHERE "todoItem"."OwnerId" = @___authService_CurrentUserId_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@___authService_CurrentUserId_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "todoItem"
+      WHERE "todoItem"."OwnerId" = @___authService_CurrentUserId_0
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem todoItem in DbSet<TodoItem> where [todoItem].OwnerId == (Nullable<int>)___authService...' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem todoItem in DbSet<TodoItem> where [todoItem].OwnerId == (Nullable<int>)___authService...' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@___authService_CurrentUserId_0='?', @__p_2='?', @__p_1='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "todoItem"."Id", "todoItem"."AchievedDate", "todoItem"."AssigneeId", "todoItem"."CollectionId", "todoItem"."CreatedDate", "todoItem"."Description", "todoItem"."GuidProperty", "todoItem"."Ordinal", "todoItem"."OwnerId", "todoItem.Owner"."Id", "todoItem.Owner"."FirstName", "todoItem.Owner"."LastName"
+      FROM "TodoItems" AS "todoItem"
+      LEFT JOIN "People" AS "todoItem.Owner" ON "todoItem"."OwnerId" = "todoItem.Owner"."Id"
+      WHERE "todoItem"."OwnerId" = @___authService_CurrentUserId_0
+      LIMIT @__p_2 OFFSET @__p_1
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@___authService_CurrentUserId_0='?', @__p_2='?', @__p_1='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "todoItem"."Id", "todoItem"."AchievedDate", "todoItem"."AssigneeId", "todoItem"."CollectionId", "todoItem"."CreatedDate", "todoItem"."Description", "todoItem"."GuidProperty", "todoItem"."Ordinal", "todoItem"."OwnerId", "todoItem.Owner"."Id", "todoItem.Owner"."FirstName", "todoItem.Owner"."LastName"
+      FROM "TodoItems" AS "todoItem"
+      LEFT JOIN "People" AS "todoItem.Owner" ON "todoItem"."OwnerId" = "todoItem.Owner"."Id"
+      WHERE "todoItem"."OwnerId" = @___authService_CurrentUserId_0
+      LIMIT @__p_2 OFFSET @__p_1
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 48.653ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 48.653ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 74.804ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 74.804ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExampleTests
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/people  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/people'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.PeopleController.PostAsync (JsonApiDotNetCoreExample)' with id '1ded46dd-748a-4bb3-b33b-d64481e8f7d0' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_1 in DbSet<Person>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "People" AS "p"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "People" AS "p"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 5 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from Person <generated>_2 in DbSet<Person>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from Person <generated>_2 in DbSet<Person> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from Person <generated>_2 in DbSet<Person> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from Person <generated>_2 in DbSet<Person>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<Person> _InterceptExceptions(
+          source: IAsyncEnumerable<Person> _TrackEntities(
+              results: IAsyncEnumerable<Person> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+                      FROM "People" AS "p"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<Person>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: Person }, 
+              entityAccessors: List<Func<Person, object>> 
+              { 
+                  Func<Person, Person>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "p"."Id", "p"."FirstName", "p"."LastName"
+      FROM "People" AS "p"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 54.361ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 78.817ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.PeopleController.GetAsync (JsonApiDotNetCoreExample) in 54.361ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 78.817ms 200 application/vnd.api+json
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[5]
+      Hosting shutdown
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p24, @p25, @p26, @p27, @p28, @p29, @p30, @p31)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p24, @p25, @p26, @p27, @p28, @p29, @p30, @p31)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p24, @p25, @p26, @p27, @p28, @p29, @p30, @p31)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?page[size]=2  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?page[size]=2  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '52af8b31-a0b5-47dc-9061-17639045ff8f' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (10ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 0 with 2 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 38.24ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 38.24ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 64.502ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 64.502ms 200 application/vnd.api+json
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[5]
+      Hosting shutdown
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      'from TodoItem <generated>_0 in DbSet<TodoItem>
+      select [<generated>_0]'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      'from TodoItem <generated>_0 in DbSet<TodoItem>
+      select [<generated>_0]'
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _TrackEntities(
+              results: IEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t", 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p15;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p16;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p17;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p18;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p19;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p20;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p21;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p28;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p29;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p30;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p31;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p32;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p33;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p34;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p35;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p36;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p37;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p38;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p15;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p16;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p17;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p18;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p19;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p20;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p21;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p28;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p29;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p30;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p31;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p32;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p33;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p34;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p35;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p36;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p37;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p38;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (4ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?', @p38='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p6;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p7;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p8;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p9;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p10;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p11;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p12;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p13;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p14;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p15;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p16;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p17;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p18;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p19;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p20;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p21;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p22;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p23;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p24;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p25;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p26;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p27;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p28;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p29;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p30;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p31;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p32;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p33;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p34;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p35;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p36;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p37;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p38;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?', @p67='?', @p68='?', @p69='?', @p70='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p47, @p48, @p49, @p50, @p51, @p52, @p53, @p54)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p55, @p56, @p57, @p58, @p59, @p60, @p61, @p62)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p63, @p64, @p65, @p66, @p67, @p68, @p69, @p70)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?', @p67='?', @p68='?', @p69='?', @p70='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p47, @p48, @p49, @p50, @p51, @p52, @p53, @p54)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p55, @p56, @p57, @p58, @p59, @p60, @p61, @p62)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p63, @p64, @p65, @p66, @p67, @p68, @p69, @p70)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[@p39='?', @p40='?', @p41='?', @p42='?', @p43='?', @p44='?', @p45='?', @p46='?', @p47='?', @p48='?', @p49='?', @p50='?', @p51='?', @p52='?', @p53='?', @p54='?', @p55='?', @p56='?', @p57='?', @p58='?', @p59='?', @p60='?', @p61='?', @p62='?', @p63='?', @p64='?', @p65='?', @p66='?', @p67='?', @p68='?', @p69='?', @p70='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p47, @p48, @p49, @p50, @p51, @p52, @p53, @p54)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p55, @p56, @p57, @p58, @p59, @p60, @p61, @p62)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p63, @p64, @p65, @p66, @p67, @p68, @p69, @p70)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?page[size]=2&page[number]=1  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?page[size]=2&page[number]=1  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '8b075eda-2371-4b4f-8774-1f6d937181b9' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page 1 with 2 entities
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 32.06ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 32.06ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 56.326ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 56.326ms 200 application/vnd.api+json
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[5]
+      Hosting shutdown
+dbug: Microsoft.EntityFrameworkCore.Infrastructure[10401]
+      An 'IServiceProvider' was created for internal use by Entity Framework.
+warn: Microsoft.EntityFrameworkCore.Infrastructure[10402]
+      More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.
+info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
+      User profile is available. Using '/Users/jarednance/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-b040dd03-33c5-451e-8f42-3c9dd4e0dfec.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-c8147b66-2deb-407c-9421-1553f0e16d67.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[37]
+      Reading data from file '/Users/jarednance/.aspnet/DataProtection-Keys/key-f7fa4a09-6d65-426e-a653-cbd2969e5073.xml'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {b040dd03-33c5-451e-8f42-3c9dd4e0dfec}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {c8147b66-2deb-407c-9421-1553f0e16d67}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[18]
+      Found key {f7fa4a09-6d65-426e-a653-cbd2969e5073}.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[13]
+      Considering key {c8147b66-2deb-407c-9421-1553f0e16d67} with expiration date 2018-03-03 16:22:35Z as default key.
+dbug: Microsoft.AspNetCore.DataProtection.TypeForwardingActivator[0]
+      Forwarded activator type request from Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 to Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Culture=neutral, PublicKeyToken=adb9793829ddae60
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[11]
+      Using managed symmetric algorithm 'System.Security.Cryptography.Aes'.
+dbug: Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory[10]
+      Using managed keyed hash algorithm 'System.Security.Cryptography.HMACSHA256'.
+dbug: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[2]
+      Using key {c8147b66-2deb-407c-9421-1553f0e16d67} as the default key.
+dbug: Microsoft.AspNetCore.DataProtection.Internal.DataProtectionStartupFilter[0]
+      Key ring with default key {c8147b66-2deb-407c-9421-1553f0e16d67} was loaded during application startup.
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      
+                          SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
+                          FROM information_schema.tables
+                          WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
+      Hosting starting
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
+      Hosting started
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
+      Loaded hosting startup assembly JsonApiDotNetCoreExample
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      'from TodoItem <generated>_0 in DbSet<TodoItem>
+      select [<generated>_0]'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      'from TodoItem <generated>_0 in DbSet<TodoItem>
+      select [<generated>_0]'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IEnumerable<TodoItem> _InterceptExceptions(
+          source: IEnumerable<TodoItem> _TrackEntities(
+              results: IEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t", 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20200]
+      Beginning transaction with isolation level 'ReadCommitted'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "People" ("FirstName", "LastName")
+      VALUES (@p0, @p1)
+      RETURNING "Id";
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p2;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p3;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p4;
+      DELETE FROM "TodoItems"
+      WHERE "Id" = @p5;
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p30, @p31, @p32, @p33, @p34, @p35, @p36, @p37)
+      RETURNING "Id";
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p30, @p31, @p32, @p33, @p34, @p35, @p36, @p37)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?', @p17='?', @p18='?', @p19='?', @p20='?', @p21='?', @p22='?', @p23='?', @p24='?', @p25='?', @p26='?', @p27='?', @p28='?', @p29='?', @p30='?', @p31='?', @p32='?', @p33='?', @p34='?', @p35='?', @p36='?', @p37='?'], CommandType='Text', CommandTimeout='30']
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29)
+      RETURNING "Id";
+      INSERT INTO "TodoItems" ("AchievedDate", "AssigneeId", "CollectionId", "CreatedDate", "Description", "GuidProperty", "Ordinal", "OwnerId")
+      VALUES (@p30, @p31, @p32, @p33, @p34, @p35, @p36, @p37)
+      RETURNING "Id";
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20202]
+      Committing transaction.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Transaction[20204]
+      Disposing transaction.
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?page[size]=2&page[number]=-1  
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
+      Request starting HTTP/1.1 GET http://localhost/api/v1/todo-items?page[size]=2&page[number]=-1  
+dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
+      Request successfully matched the route with name '(null)' and template 'api/v1/todo-items'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
+      Action 'JsonApiDotNetCoreExample.Controllers.TodoItemsController.PostAsync (JsonApiDotNetCoreExample)' with id '0185f6c8-2dbf-416d-abd0-a7a72d063bea' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample)
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
+      Executing action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) with arguments ((null)) - ModelState is Valid
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
+      Entity Framework Core 2.0.1-rtm-125 initialized 'AppDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_1 in DbSet<TodoItem>
+      select [<generated>_1]).Count()'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<int> _InterceptExceptions(
+          source: IAsyncEnumerable<int> _ToSequence(Task<int> GetResult(
+                  valueBuffers: IAsyncEnumerable<ValueBuffer> _Query(
+                      queryContext: queryContext, 
+                      shaperCommandContext: SelectExpression: 
+                          SELECT COUNT(*)::INT4
+                          FROM "TodoItems" AS "t"), 
+                  throwOnNullResult: False, 
+                  cancellationToken: queryContext.CancellationToken)), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: JsonApiDotNetCore.Services.EntityResourceService[0]
+      Applying paging query. Fetching page -1 with 2 entities
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
+      SELECT COUNT(*)::INT4
+      FROM "TodoItems" AS "t"
+dbug: Microsoft.EntityFrameworkCore.Query[10101]
+      Compiling query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+warn: Microsoft.EntityFrameworkCore.Query[10102]
+      Query: '(from TodoItem <generated>_2 in DbSet<TodoItem> select [<generated>_2]).Skip(__p_0).Take(__p_1)' uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results.
+dbug: Microsoft.EntityFrameworkCore.Query[10104]
+      Optimized query model: 
+      '(from TodoItem <generated>_2 in DbSet<TodoItem>
+      select [<generated>_2])
+      .Skip(__p_0)
+      .Take(__p_1)'
+dbug: Microsoft.EntityFrameworkCore.Query[10107]
+      (QueryContext queryContext) => IAsyncEnumerable<TodoItem> _InterceptExceptions(
+          source: IAsyncEnumerable<TodoItem> _TrackEntities(
+              results: IAsyncEnumerable<TodoItem> _ShapedQuery(
+                  queryContext: queryContext, 
+                  shaperCommandContext: SelectExpression: 
+                      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+                      FROM "TodoItems" AS "t"
+                      LIMIT @__p_1 OFFSET @__p_0, 
+                  shaper: UnbufferedEntityShaper<TodoItem>), 
+              queryContext: queryContext, 
+              entityTrackingInfos: { itemType: TodoItem }, 
+              entityAccessors: List<Func<TodoItem, object>> 
+              { 
+                  Func<TodoItem, TodoItem>, 
+              }
+          ), 
+          contextType: JsonApiDotNetCoreExample.Data.AppDbContext, 
+          logger: DiagnosticsLogger<Query>, 
+          queryContext: queryContext)
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
+      Opening connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
+      Opened connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
+      Executing DbCommand [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+info: Microsoft.EntityFrameworkCore.Database.Command[20101]
+      Executed DbCommand (1ms) [Parameters=[@__p_1='?', @__p_0='?'], CommandType='Text', CommandTimeout='30']
+      SELECT "t"."Id", "t"."AchievedDate", "t"."AssigneeId", "t"."CollectionId", "t"."CreatedDate", "t"."Description", "t"."GuidProperty", "t"."Ordinal", "t"."OwnerId"
+      FROM "TodoItems" AS "t"
+      LIMIT @__p_1 OFFSET @__p_0
+dbug: Microsoft.EntityFrameworkCore.Database.Command[20300]
+      A data reader was disposed.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20002]
+      Closing connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.EntityFrameworkCore.Database.Connection[20003]
+      Closed connection to database 'JsonApiDotNetCoreExample' on server 'tcp://localhost:5432'.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action method JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample), returned result Microsoft.AspNetCore.Mvc.OkObjectResult.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[4]
+      No information found on request to perform content negotiation.
+dbug: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[2]
+      Selected output formatter 'JsonApiDotNetCore.Formatters.JsonApiOutputFormatter' and content type '' to write the response.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]
+      Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
+info: JsonApiDotNetCore.Formatters.JsonApiWriter[0]
+      Formatting response as JSONAPI
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 38.909ms
+info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
+      Executed action JsonApiDotNetCoreExample.Controllers.TodoItemsController.GetAsync (JsonApiDotNetCoreExample) in 38.909ms
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 63.599ms 200 application/vnd.api+json
+info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
+      Request finished in 63.599ms 200 application/vnd.api+json
+dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[5]
+      Hosting shutdown
+[xUnit.net 00:00:22.5994190]   Finished:    JsonApiDotNetCoreExampleTests
+
+Total tests: 111. Passed: 110. Failed: 1. Skipped: 0.
+Test execution time: 23.7537 Seconds
diff --git a/test/UnitTests/Serialization/JsonApiSerializerTests.cs b/test/UnitTests/Serialization/JsonApiSerializerTests.cs
index 3630cd6452..8a67b80434 100644
--- a/test/UnitTests/Serialization/JsonApiSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiSerializerTests.cs
@@ -1,14 +1,10 @@
-using System.Collections.Generic;
-using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
 using Moq;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Serialization;
 using Xunit;
 
 namespace UnitTests.Serialization
@@ -47,7 +43,7 @@ public void Can_Serialize_Complex_Types()
 
             // assert
             Assert.NotNull(result);
-            Assert.Equal("{\"data\":{\"type\":\"test-resource\",\"id\":\"\",\"attributes\":{\"complex-member\":{\"compound-name\":\"testname\"}}}}", result);
+            Assert.Equal("{\"data\":{\"attributes\":{\"complex-member\":{\"compound-name\":\"testname\"}},\"type\":\"test-resource\",\"id\":\"\"}}", result);
         }
 
         private class TestResource : Identifiable

From 4a65704a2a2c2785c0645888a4aae7e9763c684f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 1 Mar 2018 06:04:36 -0600
Subject: [PATCH 093/227] fix(deserialization): deserialize operations document

---
 .../IServiceCollectionExtensions.cs           |  1 -
 .../Formatters/JsonApiOperationsReader.cs     | 43 -------------------
 .../Formatters/JsonApiReader.cs               |  3 +-
 .../Serialization/JsonApiDeSerializer.cs      | 18 +++++++-
 .../Operations/OperationsProcessor.cs         |  6 +--
 5 files changed, 21 insertions(+), 50 deletions(-)
 delete mode 100644 src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs

diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 437132f087..1f2a71e20b 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -129,7 +129,6 @@ public static void AddJsonApiInternals(
             services.AddScoped<IJsonApiWriter, JsonApiWriter>();
             services.AddScoped<IJsonApiDeSerializer, JsonApiDeSerializer>();
             services.AddScoped<IJsonApiReader, JsonApiReader>();
-            services.AddScoped<IJsonApiOperationsReader, JsonApiOperationsReader>();
             services.AddScoped<IGenericProcessorFactory, GenericProcessorFactory>();
             services.AddScoped(typeof(GenericProcessor<>));
             services.AddScoped(typeof(GenericProcessor<,>));
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
deleted file mode 100644
index 912cac2fff..0000000000
--- a/src/JsonApiDotNetCore/Formatters/JsonApiOperationsReader.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System;
-using System.IO;
-using System.Threading.Tasks;
-using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Models.Operations;
-using Microsoft.AspNetCore.Mvc.Formatters;
-using Newtonsoft.Json;
-
-namespace JsonApiDotNetCore.Formatters
-{
-    public interface IJsonApiOperationsReader
-    {
-        Task<InputFormatterResult> ReadAsync(InputFormatterContext context);
-    }
-
-    public class JsonApiOperationsReader : IJsonApiOperationsReader
-    {
-        public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
-        {
-            if (context == null)
-                throw new ArgumentNullException(nameof(context));
-
-            var request = context.HttpContext.Request;
-            if (request.ContentLength == null || request.ContentLength == 0)
-                throw new JsonApiException(400, "Content-Length cannot be empty.");
-
-            var body = GetRequestBody(request.Body);
-
-            var operations = JsonConvert.DeserializeObject<OperationsDocument>(body);
-
-            if (operations == null)
-                throw new JsonApiException(400, "Failed to deserialize operations request.");
-
-            return InputFormatterResult.SuccessAsync(operations);
-        }
-
-        private string GetRequestBody(Stream body)
-        {
-            using (var reader = new StreamReader(body))
-                return reader.ReadToEnd();
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs b/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs
index 274d14bc15..204f3e0491 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs
@@ -36,6 +36,7 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
             try
             {
                 var body = GetRequestBody(context.HttpContext.Request.Body);
+
                 var model = _jsonApiContext.IsRelationshipPath ?
                     _deSerializer.DeserializeRelationship(body) :
                     _deSerializer.Deserialize(body);
@@ -67,4 +68,4 @@ private string GetRequestBody(Stream body)
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index ef7938dbd3..a32a40c5d4 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -5,6 +5,7 @@
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Services;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
@@ -28,7 +29,20 @@ public object Deserialize(string requestBody)
         {
             try
             {
-                var document = JsonConvert.DeserializeObject<Document>(requestBody);
+                // TODO: determine whether or not the token should be re-used rather than performing full
+                // deserialization again from the string
+                var bodyJToken = JToken.Parse(requestBody);
+                if(bodyJToken.SelectToken("operations") != null)
+                {
+                    var operations = JsonConvert.DeserializeObject<OperationsDocument>(requestBody);
+                    if (operations == null)
+                        throw new JsonApiException(400, "Failed to deserialize operations request.");
+
+                    return operations;
+                }
+
+                var document = bodyJToken.ToObject<Document>();
+
                 _jsonApiContext.DocumentMeta = document.Meta;
                 var entity = DocumentToObject(document.Data);
                 return entity;
@@ -63,7 +77,7 @@ public List<TEntity> DeserializeList<TEntity>(string requestBody)
             try
             {
                 var documents = JsonConvert.DeserializeObject<Documents>(requestBody);
-
+                
                 var deserializedList = new List<TEntity>();
                 foreach (var data in documents.Data)
                 {
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index e49e758570..a0ab3f2d65 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -1,8 +1,8 @@
 using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Models.Pointers;
 using Microsoft.EntityFrameworkCore;
@@ -21,10 +21,10 @@ public class OperationsProcessor : IOperationsProcessor
 
         public OperationsProcessor(
             IOperationProcessorResolver processorResolver,
-            DbContext dbContext)
+            IDbContextResolver dbContextResolver)
         {
             _processorResolver = processorResolver;
-            _dbContext = dbContext;
+            _dbContext = dbContextResolver.GetContext();
         }
 
         public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)

From 9b93e42040fbdabc24e81eea3ae6770d49dfe58f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 1 Mar 2018 06:10:31 -0600
Subject: [PATCH 094/227] test(operations): use dbcontext resolver

---
 .../Services/Operations/OperationsProcessorTests.cs        | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
index fb098d3f78..c8d739104b 100644
--- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -1,6 +1,7 @@
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Services.Operations;
 using Microsoft.EntityFrameworkCore;
@@ -15,13 +16,15 @@ namespace UnitTests.Services
     public class OperationsProcessorTests
     {
         private readonly Mock<IOperationProcessorResolver> _resolverMock;
-
         public readonly Mock<DbContext> _dbContextMock;
+        public readonly Mock<IDbContextResolver> _dbContextResolverMock;
 
         public OperationsProcessorTests()
         {
             _resolverMock = new Mock<IOperationProcessorResolver>();
             _dbContextMock = new Mock<DbContext>();
+            _dbContextResolverMock = new Mock<IDbContextResolver>();
+            _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object);
         }
 
         [Fact]
@@ -88,7 +91,7 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
             _resolverMock.Setup(m => m.LocateCreateService((It.IsAny<Operation>())))
                 .Returns(opProcessorMock.Object);
 
-            var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextMock.Object);
+            var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextResolverMock.Object);
 
             // act
             var results = await operationsProcessor.ProcessAsync(operations);

From 86c1b56171550cae52668bcdcfe426ba07365dad Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 1 Mar 2018 06:35:32 -0600
Subject: [PATCH 095/227] use local ids instead of JsonPointers

---
 .../Operations/OperationsProcessor.cs         | 41 ++++++++++++++++++-
 .../Operations/OperationsProcessorTests.cs    |  6 ++-
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index a0ab3f2d65..cefcd2ebca 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -1,8 +1,10 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Models.Pointers;
 using Microsoft.EntityFrameworkCore;
@@ -61,7 +63,7 @@ private async Task ProcessOperation(Operation op, List<Operation> outputOps)
         {
             var operationsPointer = new OperationsPointer();
 
-            // ReplaceDataPointers(op.DataObject, outputOps);
+            ReplaceDataPointers(op.DataObject, outputOps);
             // ReplaceRefPointers(op.Ref, outputOps);
 
             var processor = GetOperationsProcessor(op);
@@ -71,6 +73,43 @@ private async Task ProcessOperation(Operation op, List<Operation> outputOps)
                 outputOps.Add(resultOp);
         }
 
+        private void ReplaceDataPointers(DocumentData data, List<Operation> outputOps)
+        {
+            if (data == null) return;
+
+            bool HasLocalId(ResourceIdentifierObject rio) => string.IsNullOrEmpty(rio.LocalId) == false;
+            string GetIdFromLocalId(string localId)  {
+                var referencedOp = outputOps.FirstOrDefault(o => o.DataObject.LocalId == localId);
+                if(referencedOp == null) throw new JsonApiException(400, $"Could not locate lid '{localId}' in document.");
+                return referencedOp.DataObject.Id;
+            };
+
+            // are there any circumstances where the primary data would contain an lid?
+            // if(HasLocalId(data))
+            // {
+            //     data.Id = GetIdFromLocalId(data.LocalId);
+            // }
+
+            if (data.Relationships != null) 
+            { 
+                foreach (var relationshipDictionary in data.Relationships) 
+                { 
+                    if (relationshipDictionary.Value.IsHasMany) 
+                    { 
+                        foreach (var relationship in relationshipDictionary.Value.ManyData) 
+                            if(HasLocalId(relationship))
+                                relationship.Id = GetIdFromLocalId(relationship.LocalId);
+                    } 
+                    else
+                    {
+                        var relationship = relationshipDictionary.Value.SingleData;
+                        if(HasLocalId(relationship))
+                            relationship.Id = GetIdFromLocalId(relationship.LocalId);
+                    }
+                } 
+            }
+        }
+
         private IOpProcessor GetOperationsProcessor(Operation op)
         {
             switch (op.Op)
diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
index c8d739104b..04272d25b3 100644
--- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -24,7 +24,6 @@ public OperationsProcessorTests()
             _resolverMock = new Mock<IOperationProcessorResolver>();
             _dbContextMock = new Mock<DbContext>();
             _dbContextResolverMock = new Mock<IDbContextResolver>();
-            _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object);
         }
 
         [Fact]
@@ -36,6 +35,7 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
                     ""op"": ""add"",
                     ""data"": {
                         ""type"": ""authors"",
+                        ""lid"": ""a"",
                         ""attributes"": {
                             ""name"": ""dgeb""
                         }
@@ -51,7 +51,7 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
                             ""author"": {
                                 ""data"": {
                                     ""type"": ""authors"",
-                                    ""id"": { ""pointer"": ""/operations/0/data/id"" }
+                                    ""lid"": ""a""
                                 }
                             }
                         }
@@ -66,6 +66,7 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
                 ""data"": {
                     ""type"": ""authors"",
                     ""id"": ""9"",
+                    ""lid"": ""a"",
                     ""attributes"": {
                         ""name"": ""dgeb""
                     }
@@ -91,6 +92,7 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
             _resolverMock.Setup(m => m.LocateCreateService((It.IsAny<Operation>())))
                 .Returns(opProcessorMock.Object);
 
+            _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object);
             var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextResolverMock.Object);
 
             // act

From 3b08bdb7d435c46c6f4f11b23df263b71ad9a938 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 2 Mar 2018 07:17:02 -0600
Subject: [PATCH 096/227] replace ref.lid with results ids

---
 .../Models/Operations/ResourceReference.cs    |  8 +-
 .../Operations/OperationsProcessor.cs         | 58 +++++++-----
 .../Operations/OperationsProcessorTests.cs    | 90 ++++++++++++++++++-
 3 files changed, 123 insertions(+), 33 deletions(-)

diff --git a/src/JsonApiDotNetCore/Models/Operations/ResourceReference.cs b/src/JsonApiDotNetCore/Models/Operations/ResourceReference.cs
index a8caa7ca05..5291d61a19 100644
--- a/src/JsonApiDotNetCore/Models/Operations/ResourceReference.cs
+++ b/src/JsonApiDotNetCore/Models/Operations/ResourceReference.cs
@@ -2,14 +2,8 @@
 
 namespace JsonApiDotNetCore.Models.Operations
 {
-    public class ResourceReference
+    public class ResourceReference : ResourceIdentifierObject
     {
-        [JsonProperty("type")]
-        public object Type { get; set; }
-
-        [JsonProperty("id")]
-        public object Id { get; set; }
-        
         [JsonProperty("relationship")]
         public string Relationship { get; set; }
     }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index cefcd2ebca..b687f1498f 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -33,6 +33,7 @@ public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
         {
             var outputOps = new List<Operation>();
             var opIndex = 0;
+
             using (var transaction = await _dbContext.Database.BeginTransactionAsync())
             {
                 try
@@ -63,8 +64,8 @@ private async Task ProcessOperation(Operation op, List<Operation> outputOps)
         {
             var operationsPointer = new OperationsPointer();
 
-            ReplaceDataPointers(op.DataObject, outputOps);
-            // ReplaceRefPointers(op.Ref, outputOps);
+            ReplaceLocalIdsInResourceObject(op.DataObject, outputOps);
+            ReplaceLocalIdsInRef(op.Ref, outputOps);
 
             var processor = GetOperationsProcessor(op);
             var resultOp = await processor.ProcessAsync(op);
@@ -73,43 +74,56 @@ private async Task ProcessOperation(Operation op, List<Operation> outputOps)
                 outputOps.Add(resultOp);
         }
 
-        private void ReplaceDataPointers(DocumentData data, List<Operation> outputOps)
+        private void ReplaceLocalIdsInResourceObject(ResourceObject resourceObject, List<Operation> outputOps)
         {
-            if (data == null) return;
-
-            bool HasLocalId(ResourceIdentifierObject rio) => string.IsNullOrEmpty(rio.LocalId) == false;
-            string GetIdFromLocalId(string localId)  {
-                var referencedOp = outputOps.FirstOrDefault(o => o.DataObject.LocalId == localId);
-                if(referencedOp == null) throw new JsonApiException(400, $"Could not locate lid '{localId}' in document.");
-                return referencedOp.DataObject.Id;
-            };
-
-            // are there any circumstances where the primary data would contain an lid?
-            // if(HasLocalId(data))
-            // {
-            //     data.Id = GetIdFromLocalId(data.LocalId);
-            // }
-
-            if (data.Relationships != null) 
+            if (resourceObject == null) return;
+
+            // it is strange to me that a top level resource object might use a lid.
+            // by not replacing it, we avoid a case where the first operation is an 'add' with an 'lid'
+            // and we would be unable to locate the matching 'lid' in 'outputOps'
+            //
+            // we also create a scenario where I might try to update a resource I just created
+            // in this case, the 'data.id' will be null, but the 'ref.id' will be replaced by the correct 'id' from 'outputOps'
+            // 
+            // if(HasLocalId(resourceObject))
+            //     resourceObject.Id = GetIdFromLocalId(outputOps, resourceObject.LocalId);
+
+            if (resourceObject.Relationships != null) 
             { 
-                foreach (var relationshipDictionary in data.Relationships) 
+                foreach (var relationshipDictionary in resourceObject.Relationships) 
                 { 
                     if (relationshipDictionary.Value.IsHasMany) 
                     { 
                         foreach (var relationship in relationshipDictionary.Value.ManyData) 
                             if(HasLocalId(relationship))
-                                relationship.Id = GetIdFromLocalId(relationship.LocalId);
+                                relationship.Id = GetIdFromLocalId(outputOps, relationship.LocalId);
                     } 
                     else
                     {
                         var relationship = relationshipDictionary.Value.SingleData;
                         if(HasLocalId(relationship))
-                            relationship.Id = GetIdFromLocalId(relationship.LocalId);
+                            relationship.Id = GetIdFromLocalId(outputOps, relationship.LocalId);
                     }
                 } 
             }
         }
 
+        private void ReplaceLocalIdsInRef(ResourceReference resourceRef, List<Operation> outputOps) 
+        { 
+            if (resourceRef == null) return;
+            if(HasLocalId(resourceRef))
+                resourceRef.Id = GetIdFromLocalId(outputOps, resourceRef.LocalId);
+        }
+
+        private bool HasLocalId(ResourceIdentifierObject rio) => string.IsNullOrEmpty(rio.LocalId) == false;
+
+        private string GetIdFromLocalId(List<Operation> outputOps, string localId)  
+        {
+            var referencedOp = outputOps.FirstOrDefault(o => o.DataObject.LocalId == localId);
+            if(referencedOp == null) throw new JsonApiException(400, $"Could not locate lid '{localId}' in document.");
+            return referencedOp.DataObject.Id;
+        }
+
         private IOpProcessor GetOperationsProcessor(Operation op)
         {
             switch (op.Op)
diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
index 04272d25b3..0a7fd501ae 100644
--- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -27,7 +27,7 @@ public OperationsProcessorTests()
         }
 
         [Fact]
-        public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
+        public async Task ProcessAsync_Performs_LocalId_ReplacementAsync_In_Relationships()
         {
             // arrange
             var request = @"[
@@ -89,9 +89,6 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
             _resolverMock.Setup(m => m.LocateCreateService(It.IsAny<Operation>()))
                 .Returns(opProcessorMock.Object);
 
-            _resolverMock.Setup(m => m.LocateCreateService((It.IsAny<Operation>())))
-                .Returns(opProcessorMock.Object);
-
             _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object);
             var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextResolverMock.Object);
 
@@ -108,5 +105,90 @@ public async Task ProcessAsync_Performs_Pointer_ReplacementAsync()
                 )
             );
         }
+
+        [Fact]
+        public async Task ProcessAsync_Performs_LocalId_ReplacementAsync_In_References()
+        {
+            // arrange
+            var request = @"[
+                {
+                    ""op"": ""add"",
+                    ""data"": {
+                        ""type"": ""authors"",
+                        ""lid"": ""a"",
+                        ""attributes"": {
+                            ""name"": ""jaredcnance""
+                        }
+                    }
+                }, {
+                    ""op"": ""replace"",
+                    ""ref"": {
+                        ""type"": ""authors"",
+                        ""lid"": ""a""
+                    },
+                    ""data"": {
+                        ""type"": ""authors"",
+                        ""lid"": ""a"",
+                        ""attributes"": {
+                            ""name"": ""jnance""
+                        }
+                    }
+                }
+            ]";
+
+            var op1Result = @"{
+                ""data"": {
+                    ""type"": ""authors"",
+                    ""id"": ""9"",
+                    ""lid"": ""a"",
+                    ""attributes"": {
+                        ""name"": ""jaredcnance""
+                    }
+                }
+            }";
+
+            var operations = JsonConvert.DeserializeObject<List<Operation>>(request);
+            var addOperationResult = JsonConvert.DeserializeObject<Operation>(op1Result);
+
+            var databaseMock = new Mock<DatabaseFacade>(_dbContextMock.Object);
+            var transactionMock = new Mock<IDbContextTransaction>();
+
+            databaseMock.Setup(m => m.BeginTransactionAsync(It.IsAny<CancellationToken>()))
+                .ReturnsAsync(transactionMock.Object);
+
+            _dbContextMock.Setup(m => m.Database).Returns(databaseMock.Object);
+
+            // setup add
+            var addOpProcessorMock = new Mock<IOpProcessor>();
+            addOpProcessorMock.Setup(m => m.ProcessAsync(It.Is<Operation>(op => op.DataObject.Type.ToString() == "authors")))
+                .ReturnsAsync(addOperationResult);
+            _resolverMock.Setup(m => m.LocateCreateService(It.IsAny<Operation>()))
+                .Returns(addOpProcessorMock.Object);
+
+            // setup update
+            var updateOpProcessorMock = new Mock<IOpProcessor>();
+            updateOpProcessorMock.Setup(m => m.ProcessAsync(It.Is<Operation>(op => op.DataObject.Type.ToString() == "authors")))
+                .ReturnsAsync((Operation)null);
+            _resolverMock.Setup(m => m.LocateReplaceService(It.IsAny<Operation>()))
+                .Returns(updateOpProcessorMock.Object);
+
+            _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object);
+            var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextResolverMock.Object);
+
+            // act
+            var results = await operationsProcessor.ProcessAsync(operations);
+
+            // assert
+            updateOpProcessorMock.Verify(
+                m => m.ProcessAsync(
+                    It.Is<Operation>(o =>
+                        o.DataObject.Type.ToString() == "authors"
+                        // && o.DataObject.Id == "9" // currently, we will not replace the data.id member
+                        && o.DataObject.Id == null
+                        && o.Ref.Id == "9"
+                    )
+                )
+            );
+        }
     }
 }

From e2396acafb7920ccabfb6c97a5e7e77e5f9acaea Mon Sep 17 00:00:00 2001
From: Nathan Wise <nathanwise@gmail.com>
Date: Fri, 23 Mar 2018 15:25:59 -0400
Subject: [PATCH 097/227] Initializing PageOffset to be 1 (instead of default
 0) so that the 'next' pagination link is set properly when no 'page[number]'
 is passed in the query string.

---
 src/JsonApiDotNetCore/Internal/Query/PageQuery.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Internal/Query/PageQuery.cs b/src/JsonApiDotNetCore/Internal/Query/PageQuery.cs
index 8fe66d7d67..7c09d4c386 100644
--- a/src/JsonApiDotNetCore/Internal/Query/PageQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/PageQuery.cs
@@ -3,6 +3,6 @@ namespace JsonApiDotNetCore.Internal.Query
     public class PageQuery
     {
        public int PageSize { get; set; }
-       public int PageOffset { get; set; }
+       public int PageOffset { get; set; } = 1;
     }
 }
\ No newline at end of file

From a292b2778cba40ea531ec0057547a445b51c3f7f Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Sat, 24 Mar 2018 11:43:36 -0500
Subject: [PATCH 098/227] chore(sln): clean up solution

---
 JsonApiDotnetCore.sln                         | 64 +++++++++----------
 .../Properties/launchSettings.json            | 27 ++++++++
 2 files changed, 59 insertions(+), 32 deletions(-)
 create mode 100644 src/Examples/OperationsExample/Properties/launchSettings.json

diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index d62f8db6af..e88699eabf 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -1,6 +1,6 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
-VisualStudioVersion = 15.0.27004.2009
+VisualStudioVersion = 15.0.27130.2010
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\JsonApiDotNetCore\JsonApiDotNetCore.csproj", "{C0EC9E70-EB2E-436F-9D94-FA16FA774123}"
 EndProject
@@ -32,9 +32,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks",
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "benchmarks\Benchmarks.csproj", "{1F604666-BB0F-413E-922D-9D37C6073285}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OperationsExample", "src\Examples\OperationsExample\OperationsExample.csproj", "{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OperationsExample", "src\Examples\OperationsExample\OperationsExample.csproj", "{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OperationsExampleTests", "test\OperationsExampleTests\OperationsExampleTests.csproj", "{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OperationsExampleTests", "test\OperationsExampleTests\OperationsExampleTests.csproj", "{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -114,34 +114,10 @@ Global
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Debug|x86.Build.0 = Debug|Any CPU
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|Any CPU.Build.0 = Release|Any CPU
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.ActiveCfg = Release|x64
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|x64
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|x86
-		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|x86
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.ActiveCfg = Debug|x64
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.Build.0 = Debug|x64
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.ActiveCfg = Debug|x86
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.Build.0 = Debug|x86
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.Build.0 = Release|Any CPU
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.ActiveCfg = Release|x64
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.Build.0 = Release|x64
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.ActiveCfg = Release|x86
-		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.Build.0 = Release|x86
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.ActiveCfg = Debug|x64
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.Build.0 = Debug|x64
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.ActiveCfg = Debug|x86
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.Build.0 = Debug|x86
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.Build.0 = Release|Any CPU
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.ActiveCfg = Release|x64
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.Build.0 = Release|x64
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.ActiveCfg = Release|x86
-		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.Build.0 = Release|x86
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.ActiveCfg = Release|Any CPU
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|Any CPU
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|Any CPU
+		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -154,6 +130,30 @@ Global
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x64.Build.0 = Release|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.ActiveCfg = Release|Any CPU
 		{1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.Build.0 = Release|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.Build.0 = Debug|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.Build.0 = Debug|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.ActiveCfg = Release|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.Build.0 = Release|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.ActiveCfg = Release|Any CPU
+		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.Build.0 = Release|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.Build.0 = Debug|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.Build.0 = Debug|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.ActiveCfg = Release|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.Build.0 = Release|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.ActiveCfg = Release|Any CPU
+		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -167,9 +167,9 @@ Global
 		{6D4BD85A-A262-44C6-8572-FE3A30410BF3} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
 		{026FBC6C-AF76-4568-9B87-EC73457899FD} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
 		{FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
+		{1F604666-BB0F-413E-922D-9D37C6073285} = {076E1AE4-FD25-4684-B826-CAAE37FEA0AA}
 		{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
 		{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
-		{1F604666-BB0F-413E-922D-9D37C6073285} = {076E1AE4-FD25-4684-B826-CAAE37FEA0AA}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4}
diff --git a/src/Examples/OperationsExample/Properties/launchSettings.json b/src/Examples/OperationsExample/Properties/launchSettings.json
new file mode 100644
index 0000000000..b0d8e5bd4b
--- /dev/null
+++ b/src/Examples/OperationsExample/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:53656/",
+      "sslPort": 0
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "OperationsExample": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      },
+      "applicationUrl": "http://localhost:53657/"
+    }
+  }
+}
\ No newline at end of file

From e18fa03841909fd4300fc078534b81afe3c62c1d Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 24 Mar 2018 18:49:53 -0500
Subject: [PATCH 099/227] put operation enabling behind a feature flag on
 global options

---
 src/Examples/OperationsExample/Startup.cs     | 121 +++++++++---------
 .../DocumentBuilderOptionsProvider.cs         |   3 -
 .../Configuration/JsonApiOptions.cs           | 103 +++++++++++++--
 .../IServiceCollectionExtensions.cs           |   2 +-
 .../Serialization/JsonApiDeSerializer.cs      |  11 +-
 5 files changed, 164 insertions(+), 76 deletions(-)

diff --git a/src/Examples/OperationsExample/Startup.cs b/src/Examples/OperationsExample/Startup.cs
index 1ffedf9116..7e4444dfb5 100644
--- a/src/Examples/OperationsExample/Startup.cs
+++ b/src/Examples/OperationsExample/Startup.cs
@@ -1,60 +1,61 @@
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.EntityFrameworkCore;
-using JsonApiDotNetCore.Extensions;
-using System;
-using OperationsExample.Data;
-using JsonApiDotNetCore.Models;
-
-namespace OperationsExample
-{
-    public class Startup
-    {
-        public readonly IConfiguration Config;
-
-        public Startup(IHostingEnvironment env)
-        {
-            var builder = new ConfigurationBuilder()
-                .SetBasePath(env.ContentRootPath)
-                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
-                .AddEnvironmentVariables();
-
-            Config = builder.Build();
-        }
-
-        public virtual IServiceProvider ConfigureServices(IServiceCollection services)
-        {
-            var loggerFactory = new LoggerFactory();
-            loggerFactory
-              .AddConsole(LogLevel.Trace);
-            services.AddSingleton<ILoggerFactory>(loggerFactory);
-
-            services.AddDbContext<AppDbContext>(options =>
-            {
-                options.UseNpgsql(GetDbConnectionString());
-            }, ServiceLifetime.Transient);
-
-            services.AddJsonApi<AppDbContext>(opt => opt.EnableExtension(JsonApiExtension.Operations));
-
-            return services.BuildServiceProvider();
-        }
-
-        public virtual void Configure(
-            IApplicationBuilder app,
-            IHostingEnvironment env,
-            ILoggerFactory loggerFactory,
-            AppDbContext context)
-        {
-            context.Database.EnsureCreated();
-
-            loggerFactory.AddConsole(Config.GetSection("Logging"));
-            loggerFactory.AddDebug();
-            app.UseJsonApi();
-        }
-
-        public string GetDbConnectionString() => Config["Data:DefaultConnection"];
-    }
-}
\ No newline at end of file
+using System;
+using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Models;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using OperationsExample.Data;
+
+
+namespace OperationsExample
+{
+    public class Startup
+    {
+        public readonly IConfiguration Config;
+
+        public Startup(IHostingEnvironment env)
+        {
+            var builder = new ConfigurationBuilder()
+                .SetBasePath(env.ContentRootPath)
+                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
+                .AddEnvironmentVariables();
+
+            Config = builder.Build();
+        }
+
+        public virtual IServiceProvider ConfigureServices(IServiceCollection services)
+        {
+            var loggerFactory = new LoggerFactory();
+            loggerFactory.AddConsole(LogLevel.Trace);
+
+            services.AddSingleton<ILoggerFactory>(loggerFactory);
+
+            services.AddDbContext<AppDbContext>(options =>
+            {
+                options.UseNpgsql(GetDbConnectionString());
+            }, ServiceLifetime.Transient);
+
+            services.AddJsonApi<AppDbContext>(opt => opt.EnableOperations = true);
+
+            return services.BuildServiceProvider();
+        }
+
+        public virtual void Configure(
+            IApplicationBuilder app,
+            IHostingEnvironment env,
+            ILoggerFactory loggerFactory,
+            AppDbContext context)
+        {
+            context.Database.EnsureCreated();
+
+            loggerFactory.AddConsole(Config.GetSection("Logging"));
+            loggerFactory.AddDebug();
+            app.UseJsonApi();
+        }
+
+        public string GetDbConnectionString() => Config["Data:DefaultConnection"];
+    }
+}
diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs
index af7fb78d7c..37c5d51273 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs
@@ -1,6 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
 
diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index e61c5cd429..ea8d0554e3 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -10,17 +10,106 @@
 
 namespace JsonApiDotNetCore.Configuration
 {
+    /// <summary>
+    /// Global options.
+    /// https://json-api-dotnet.github.io/#/global-options
+    /// </summary>
     public class JsonApiOptions
     {
+        /// <summary>
+        /// The base URL Namespace
+        /// </summary>
+        /// <example>
+        /// <code>options.Namespace = "api/v1";</code>
+        /// </example>
         public string Namespace { get; set; }
+
+        /// <summary>
+        /// The default page size for all resources
+        /// </summary>
+        /// <example>
+        /// <code>options.DefaultPageSize = 10;</code>
+        /// </example>
         public int DefaultPageSize { get; set; }
+
+        /// <summary>
+        /// Whether or not the total-record count should be included in all document
+        /// level meta objects.
+        /// Defaults to false.
+        /// </summary>
+        /// <example>
+        /// <code>options.IncludeTotalRecordCount = true;</code>
+        /// </example>
         public bool IncludeTotalRecordCount { get; set; }
+
+        /// <summary>
+        /// Whether or not clients can provide ids when creating resources.
+        /// Defaults to false.  When disabled the application will respond 
+        /// with a 403 Forbidden respponse if a client attempts to create a 
+        /// resource with a defined id.
+        /// </summary>
+        /// <example>
+        /// <code>options.AllowClientGeneratedIds = true;</code>
+        /// </example>
         public bool AllowClientGeneratedIds { get; set; }
+        
+        /// <summary>
+        /// The graph of all resources exposed by this application.
+        /// </summary>
         public IContextGraph ContextGraph { get; set; }
+
+        /// <summary>
+        /// Use relative links for all resources.
+        /// </summary>
+        /// <example>
+        /// <code>
+        /// options.RelativeLinks = true;
+        /// </code>
+        /// <code>
+        /// {
+        ///   "type": "articles",
+        ///   "id": "4309",
+        ///   "relationships": {
+        ///      "author": {
+        ///        "links": {
+        ///          "self": "/api/v1/articles/4309/relationships/author",
+        ///          "related": "/api/v1/articles/4309/author"
+        ///        }
+        ///      }
+        ///   }
+        /// }
+        /// </code>
+        /// </example>
         public bool RelativeLinks { get; set; }
+
+        /// <summary>
+        /// Whether or not to allow all custom query parameters.
+        /// </summary>
+        /// <example>
+        /// <code>
+        /// options.AllowCustomQueryParameters = true;
+        /// </code>
+        /// </example>
         public bool AllowCustomQueryParameters { get; set; }
+
+        /// <summary>
+        /// The default behavior for serializing null attributes.
+        /// </summary>
+        /// <example>
+        /// <code>
+        /// options.NullAttributeResponseBehavior = new NullAttributeResponseBehavior {
+        ///  // ...
+        ///};
+        /// </code>
+        /// </example>
         public NullAttributeResponseBehavior NullAttributeResponseBehavior { get; set; }
 
+        /// <summary>
+        /// Whether or not to allow json:api v1.1 operation requests
+        /// This will be enabled by default in JsonApiDotNetCore v2.2.1
+        /// </summary>
+        public bool EnableOperations { get; set; }
+
         [Obsolete("JsonContract resolver can now be set on SerializerSettings.")]
         public IContractResolver JsonContractResolver
         {
@@ -33,9 +122,6 @@ public IContractResolver JsonContractResolver
             ContractResolver = new DasherizedResolver()
         };
 
-        internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder();
-        internal List<JsonApiExtension> EnabledExtensions { get; set; } = new List<JsonApiExtension>();
-
         public void BuildContextGraph<TContext>(Action<IContextGraphBuilder> builder) where TContext : DbContext
         {
             BuildContextGraph(builder);
@@ -54,11 +140,10 @@ public void BuildContextGraph(Action<IContextGraphBuilder> builder)
             ContextGraph = ContextGraphBuilder.Build();
         }
 
-        public void EnableExtension(JsonApiExtension extension)
-        {
-            EnabledExtensions.Add(extension);
-        }
-    }
+        public void EnableExtension(JsonApiExtension extension) 
+            => EnabledExtensions.Add(extension);
 
-    
+        internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder();
+        internal List<JsonApiExtension> EnabledExtensions { get; set; } = new List<JsonApiExtension>();
+    }
 }
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 1f2a71e20b..9b33163810 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -95,7 +95,7 @@ public static void AddJsonApiInternals(
                 services.AddSingleton<DbContextOptions>(new DbContextOptionsBuilder().Options);
             }
 
-            if (jsonApiOptions.EnabledExtensions.Contains(JsonApiExtension.Operations))
+            if (jsonApiOptions.EnableOperations)
                 AddOperationServices(services);
 
             services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index a32a40c5d4..6213edfd63 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -29,11 +29,12 @@ public object Deserialize(string requestBody)
         {
             try
             {
-                // TODO: determine whether or not the token should be re-used rather than performing full
-                // deserialization again from the string
                 var bodyJToken = JToken.Parse(requestBody);
-                if(bodyJToken.SelectToken("operations") != null)
+
+                if(RequestIsOperation(bodyJToken))
                 {
+                    // TODO: determine whether or not the token should be re-used rather than performing full
+                    // deserialization again from the string
                     var operations = JsonConvert.DeserializeObject<OperationsDocument>(requestBody);
                     if (operations == null)
                         throw new JsonApiException(400, "Failed to deserialize operations request.");
@@ -53,6 +54,10 @@ public object Deserialize(string requestBody)
             }
         }
 
+        private bool RequestIsOperation(JToken bodyJToken) 
+            => _jsonApiContext.Options.EnableOperations 
+                && (bodyJToken.SelectToken("operations") != null);
+
         public TEntity Deserialize<TEntity>(string requestBody) => (TEntity)Deserialize(requestBody);
 
         public object DeserializeRelationship(string requestBody)

From 3f8b35f911b6ce6b65527f4ac84ae92e7e74440a Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 24 Mar 2018 21:28:37 -0500
Subject: [PATCH 100/227] add docfx documentation boilerplate

---
 .gitignore                                    |   4 +-
 JsonApiDotnetCore.sln                         |   5 +-
 .../JsonApiDotNetCore.csproj                  |   4 +
 src/JsonApiDotNetCore/api/.gitignore          |   4 +
 src/JsonApiDotNetCore/api/.manifest           | 683 ++++++++++++++++++
 src/JsonApiDotNetCore/api/index.md            |   2 +
 src/JsonApiDotNetCore/articles/intro.md       |   1 +
 src/JsonApiDotNetCore/articles/toc.yml        |   2 +
 src/JsonApiDotNetCore/docfx.json              |  52 ++
 src/JsonApiDotNetCore/index.md                |   4 +
 src/JsonApiDotNetCore/toc.yml                 |   5 +
 11 files changed, 763 insertions(+), 3 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/api/.gitignore
 create mode 100644 src/JsonApiDotNetCore/api/.manifest
 create mode 100644 src/JsonApiDotNetCore/api/index.md
 create mode 100644 src/JsonApiDotNetCore/articles/intro.md
 create mode 100644 src/JsonApiDotNetCore/articles/toc.yml
 create mode 100644 src/JsonApiDotNetCore/docfx.json
 create mode 100644 src/JsonApiDotNetCore/index.md
 create mode 100644 src/JsonApiDotNetCore/toc.yml

diff --git a/.gitignore b/.gitignore
index cd9f35a530..6630942ad5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,6 @@
 *.user
 .couscous/
 docs/Template-Dark/
-.idea/
\ No newline at end of file
+.idea/
+**/_site/
+log.txt
diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index e88699eabf..ac45f83cdf 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -15,6 +15,7 @@ EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C5B4D998-CECB-454D-9F32-085A897577BE}"
 	ProjectSection(SolutionItems) = preProject
 		.gitignore = .gitignore
+		Directory.Build.props = Directory.Build.props
 		README.md = README.md
 	EndProjectSection
 EndProject
@@ -160,9 +161,9 @@ Global
 	EndGlobalSection
 	GlobalSection(NestedProjects) = preSolution
 		{C0EC9E70-EB2E-436F-9D94-FA16FA774123} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
-		{97EE048B-16C0-43F6-BDA9-4E762B2F579F} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
+		{97EE048B-16C0-43F6-BDA9-4E762B2F579F} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
 		{0B959765-40D2-43B5-87EE-FE2FEF9DBED5} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
-		{570165EC-62B5-4684-A139-8D2A30DD4475} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
+		{570165EC-62B5-4684-A139-8D2A30DD4475} = {026FBC6C-AF76-4568-9B87-EC73457899FD}
 		{73DA578D-A63F-4956-83ED-6D7102E09140} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
 		{6D4BD85A-A262-44C6-8572-FE3A30410BF3} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}
 		{026FBC6C-AF76-4568-9B87-EC73457899FD} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 9fe109011b..c712227334 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -13,7 +13,11 @@
     <RepositoryType>git</RepositoryType>
     <RepositoryUrl>https://github.com/json-api-dotnet/JsonApiDotNetCore</RepositoryUrl>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
+    <DocumentationFile>bin\Release\netstandard2.0\JsonApiDotNetCore.xml</DocumentationFile>
+  </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="docfx.console" Version="2.33.0" />
     <PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
diff --git a/src/JsonApiDotNetCore/api/.gitignore b/src/JsonApiDotNetCore/api/.gitignore
new file mode 100644
index 0000000000..da7c71b83a
--- /dev/null
+++ b/src/JsonApiDotNetCore/api/.gitignore
@@ -0,0 +1,4 @@
+###############
+#  temp file  #
+###############
+*.yml
diff --git a/src/JsonApiDotNetCore/api/.manifest b/src/JsonApiDotNetCore/api/.manifest
new file mode 100644
index 0000000000..c5b25fa365
--- /dev/null
+++ b/src/JsonApiDotNetCore/api/.manifest
@@ -0,0 +1,683 @@
+{
+  "JsonApiDotNetCore.Builders": "JsonApiDotNetCore.Builders.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder.AddDbContext``1": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder.AddResource``1(System.String)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder.AddResource``2(System.String)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder.Build": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder.DocumentLinks": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder.GetAttributes(System.Type)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder.GetRelationships(System.Type)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.ContextGraphBuilder.GetRelationshipType(JsonApiDotNetCore.Models.RelationshipAttribute,System.Reflection.PropertyInfo)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilder": "JsonApiDotNetCore.Builders.DocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilder.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IRequestMeta,JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider)": "JsonApiDotNetCore.Builders.DocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilder.Build(JsonApiDotNetCore.Models.IIdentifiable)": "JsonApiDotNetCore.Builders.DocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilder.Build(System.Collections.Generic.IEnumerable{JsonApiDotNetCore.Models.IIdentifiable})": "JsonApiDotNetCore.Builders.DocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilder.GetData(JsonApiDotNetCore.Internal.ContextEntity,JsonApiDotNetCore.Models.IIdentifiable)": "JsonApiDotNetCore.Builders.DocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilderOptions": "JsonApiDotNetCore.Builders.DocumentBuilderOptions.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilderOptions.#ctor(System.Boolean)": "JsonApiDotNetCore.Builders.DocumentBuilderOptions.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilderOptions.OmitNullValuedAttributes": "JsonApiDotNetCore.Builders.DocumentBuilderOptions.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider": "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,Microsoft.AspNetCore.Http.IHttpContextAccessor)": "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.yml",
+  "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.GetDocumentBuilderOptions": "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.yml",
+  "JsonApiDotNetCore.Builders.IContextGraphBuilder": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.IContextGraphBuilder.AddDbContext``1": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.IContextGraphBuilder.AddResource``1(System.String)": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.IContextGraphBuilder.AddResource``2(System.String)": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.IContextGraphBuilder.Build": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.IContextGraphBuilder.DocumentLinks": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml",
+  "JsonApiDotNetCore.Builders.IDocumentBuilder": "JsonApiDotNetCore.Builders.IDocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.IDocumentBuilder.Build(JsonApiDotNetCore.Models.IIdentifiable)": "JsonApiDotNetCore.Builders.IDocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.IDocumentBuilder.Build(System.Collections.Generic.IEnumerable{JsonApiDotNetCore.Models.IIdentifiable})": "JsonApiDotNetCore.Builders.IDocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.IDocumentBuilder.GetData(JsonApiDotNetCore.Internal.ContextEntity,JsonApiDotNetCore.Models.IIdentifiable)": "JsonApiDotNetCore.Builders.IDocumentBuilder.yml",
+  "JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider": "JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider.yml",
+  "JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider.GetDocumentBuilderOptions": "JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider.yml",
+  "JsonApiDotNetCore.Builders.IMetaBuilder": "JsonApiDotNetCore.Builders.IMetaBuilder.yml",
+  "JsonApiDotNetCore.Builders.IMetaBuilder.Add(System.Collections.Generic.Dictionary{System.String,System.Object})": "JsonApiDotNetCore.Builders.IMetaBuilder.yml",
+  "JsonApiDotNetCore.Builders.IMetaBuilder.Add(System.String,System.Object)": "JsonApiDotNetCore.Builders.IMetaBuilder.yml",
+  "JsonApiDotNetCore.Builders.IMetaBuilder.Build": "JsonApiDotNetCore.Builders.IMetaBuilder.yml",
+  "JsonApiDotNetCore.Builders.LinkBuilder": "JsonApiDotNetCore.Builders.LinkBuilder.yml",
+  "JsonApiDotNetCore.Builders.LinkBuilder.#ctor(JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Builders.LinkBuilder.yml",
+  "JsonApiDotNetCore.Builders.LinkBuilder.GetBasePath(Microsoft.AspNetCore.Http.HttpContext,System.String)": "JsonApiDotNetCore.Builders.LinkBuilder.yml",
+  "JsonApiDotNetCore.Builders.LinkBuilder.GetPageLink(System.Int32,System.Int32)": "JsonApiDotNetCore.Builders.LinkBuilder.yml",
+  "JsonApiDotNetCore.Builders.LinkBuilder.GetRelatedRelationLink(System.String,System.String,System.String)": "JsonApiDotNetCore.Builders.LinkBuilder.yml",
+  "JsonApiDotNetCore.Builders.LinkBuilder.GetSelfRelationLink(System.String,System.String,System.String)": "JsonApiDotNetCore.Builders.LinkBuilder.yml",
+  "JsonApiDotNetCore.Builders.MetaBuilder": "JsonApiDotNetCore.Builders.MetaBuilder.yml",
+  "JsonApiDotNetCore.Builders.MetaBuilder.Add(System.Collections.Generic.Dictionary{System.String,System.Object})": "JsonApiDotNetCore.Builders.MetaBuilder.yml",
+  "JsonApiDotNetCore.Builders.MetaBuilder.Add(System.String,System.Object)": "JsonApiDotNetCore.Builders.MetaBuilder.yml",
+  "JsonApiDotNetCore.Builders.MetaBuilder.Build": "JsonApiDotNetCore.Builders.MetaBuilder.yml",
+  "JsonApiDotNetCore.Configuration": "JsonApiDotNetCore.Configuration.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.AllowClientGeneratedIds": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.AllowCustomQueryParameters": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.BuildContextGraph(System.Action{JsonApiDotNetCore.Builders.IContextGraphBuilder})": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.BuildContextGraph``1(System.Action{JsonApiDotNetCore.Builders.IContextGraphBuilder})": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.ContextGraph": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.DefaultPageSize": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.EnableExtension(JsonApiDotNetCore.Models.JsonApiExtension)": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.EnableOperations": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.IncludeTotalRecordCount": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.JsonContractResolver": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.Namespace": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.NullAttributeResponseBehavior": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.RelativeLinks": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.SerializerSettings": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior": "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.yml",
+  "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.#ctor(System.Boolean,System.Boolean)": "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.yml",
+  "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.AllowClientOverride": "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.yml",
+  "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.OmitNullValuedAttributes": "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.yml",
+  "JsonApiDotNetCore.Controllers": "JsonApiDotNetCore.Controllers.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`1": "JsonApiDotNetCore.Controllers.BaseJsonApiController-1.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IGetAllService{`0,System.Int32},JsonApiDotNetCore.Services.IGetByIdService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipsService{`0,System.Int32},JsonApiDotNetCore.Services.ICreateService{`0,System.Int32},JsonApiDotNetCore.Services.IUpdateService{`0,System.Int32},JsonApiDotNetCore.Services.IUpdateRelationshipService{`0,System.Int32},JsonApiDotNetCore.Services.IDeleteService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-1.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceQueryService{`0,System.Int32},JsonApiDotNetCore.Services.IResourceCmdService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-1.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-1.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IGetAllService{`0,`1},JsonApiDotNetCore.Services.IGetByIdService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipsService{`0,`1},JsonApiDotNetCore.Services.ICreateService{`0,`1},JsonApiDotNetCore.Services.IUpdateService{`0,`1},JsonApiDotNetCore.Services.IUpdateRelationshipService{`0,`1},JsonApiDotNetCore.Services.IDeleteService{`0,`1})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceQueryService{`0,`1},JsonApiDotNetCore.Services.IResourceCmdService{`0,`1})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.DeleteAsync(`1)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.GetAsync": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.GetAsync(`1)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.PatchAsync(`1,`0)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.PatchRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.PostAsync(`0)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.DisableQueryAttribute": "JsonApiDotNetCore.Controllers.DisableQueryAttribute.yml",
+  "JsonApiDotNetCore.Controllers.DisableQueryAttribute.#ctor(JsonApiDotNetCore.Controllers.QueryParams)": "JsonApiDotNetCore.Controllers.DisableQueryAttribute.yml",
+  "JsonApiDotNetCore.Controllers.DisableQueryAttribute.QueryParams": "JsonApiDotNetCore.Controllers.DisableQueryAttribute.yml",
+  "JsonApiDotNetCore.Controllers.DisableRoutingConventionAttribute": "JsonApiDotNetCore.Controllers.DisableRoutingConventionAttribute.yml",
+  "JsonApiDotNetCore.Controllers.HttpReadOnlyAttribute": "JsonApiDotNetCore.Controllers.HttpReadOnlyAttribute.yml",
+  "JsonApiDotNetCore.Controllers.HttpReadOnlyAttribute.Methods": "JsonApiDotNetCore.Controllers.HttpReadOnlyAttribute.yml",
+  "JsonApiDotNetCore.Controllers.HttpRestrictAttribute": "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.yml",
+  "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.Methods": "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.yml",
+  "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.OnActionExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext,Microsoft.AspNetCore.Mvc.Filters.ActionExecutionDelegate)": "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiCmdController`1": "JsonApiDotNetCore.Controllers.JsonApiCmdController-1.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiCmdController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.JsonApiCmdController-1.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiCmdController`2": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1})": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.DeleteAsync(`1)": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.PatchAsync(`1,`0)": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.PatchRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.PostAsync(`0)": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`1": "JsonApiDotNetCore.Controllers.JsonApiController-1.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IGetAllService{`0,System.Int32},JsonApiDotNetCore.Services.IGetByIdService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipsService{`0,System.Int32},JsonApiDotNetCore.Services.ICreateService{`0,System.Int32},JsonApiDotNetCore.Services.IUpdateService{`0,System.Int32},JsonApiDotNetCore.Services.IUpdateRelationshipService{`0,System.Int32},JsonApiDotNetCore.Services.IDeleteService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.JsonApiController-1.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,System.Int32},Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Controllers.JsonApiController-1.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IGetAllService{`0,`1},JsonApiDotNetCore.Services.IGetByIdService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipsService{`0,`1},JsonApiDotNetCore.Services.ICreateService{`0,`1},JsonApiDotNetCore.Services.IUpdateService{`0,`1},JsonApiDotNetCore.Services.IUpdateRelationshipService{`0,`1},JsonApiDotNetCore.Services.IDeleteService{`0,`1})": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1})": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1},Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.DeleteAsync(`1)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.GetAsync": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.GetAsync(`1)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.PatchAsync(`1,`0)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.PatchRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiController`2.PostAsync(`0)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiControllerMixin": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.Error(JsonApiDotNetCore.Internal.Error)": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.Errors(JsonApiDotNetCore.Internal.ErrorCollection)": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.Forbidden": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.UnprocessableEntity": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiOperationsController": "JsonApiDotNetCore.Controllers.JsonApiOperationsController.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiOperationsController.#ctor(JsonApiDotNetCore.Services.Operations.IOperationsProcessor)": "JsonApiDotNetCore.Controllers.JsonApiOperationsController.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiOperationsController.PatchAsync(JsonApiDotNetCore.Models.Operations.OperationsDocument)": "JsonApiDotNetCore.Controllers.JsonApiOperationsController.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiQueryController`1": "JsonApiDotNetCore.Controllers.JsonApiQueryController-1.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiQueryController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.JsonApiQueryController-1.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiQueryController`2": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1})": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.GetAsync": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.GetAsync(`1)": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml",
+  "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml",
+  "JsonApiDotNetCore.Controllers.NoHttpDeleteAttribute": "JsonApiDotNetCore.Controllers.NoHttpDeleteAttribute.yml",
+  "JsonApiDotNetCore.Controllers.NoHttpDeleteAttribute.Methods": "JsonApiDotNetCore.Controllers.NoHttpDeleteAttribute.yml",
+  "JsonApiDotNetCore.Controllers.NoHttpPatchAttribute": "JsonApiDotNetCore.Controllers.NoHttpPatchAttribute.yml",
+  "JsonApiDotNetCore.Controllers.NoHttpPatchAttribute.Methods": "JsonApiDotNetCore.Controllers.NoHttpPatchAttribute.yml",
+  "JsonApiDotNetCore.Controllers.NoHttpPostAttribute": "JsonApiDotNetCore.Controllers.NoHttpPostAttribute.yml",
+  "JsonApiDotNetCore.Controllers.NoHttpPostAttribute.Methods": "JsonApiDotNetCore.Controllers.NoHttpPostAttribute.yml",
+  "JsonApiDotNetCore.Controllers.QueryParams": "JsonApiDotNetCore.Controllers.QueryParams.yml",
+  "JsonApiDotNetCore.Controllers.QueryParams.All": "JsonApiDotNetCore.Controllers.QueryParams.yml",
+  "JsonApiDotNetCore.Controllers.QueryParams.Fields": "JsonApiDotNetCore.Controllers.QueryParams.yml",
+  "JsonApiDotNetCore.Controllers.QueryParams.Filter": "JsonApiDotNetCore.Controllers.QueryParams.yml",
+  "JsonApiDotNetCore.Controllers.QueryParams.Include": "JsonApiDotNetCore.Controllers.QueryParams.yml",
+  "JsonApiDotNetCore.Controllers.QueryParams.None": "JsonApiDotNetCore.Controllers.QueryParams.yml",
+  "JsonApiDotNetCore.Controllers.QueryParams.Page": "JsonApiDotNetCore.Controllers.QueryParams.yml",
+  "JsonApiDotNetCore.Controllers.QueryParams.Sort": "JsonApiDotNetCore.Controllers.QueryParams.yml",
+  "JsonApiDotNetCore.Data": "JsonApiDotNetCore.Data.yml",
+  "JsonApiDotNetCore.Data.DbContextResolver`1": "JsonApiDotNetCore.Data.DbContextResolver-1.yml",
+  "JsonApiDotNetCore.Data.DbContextResolver`1.#ctor(`0)": "JsonApiDotNetCore.Data.DbContextResolver-1.yml",
+  "JsonApiDotNetCore.Data.DbContextResolver`1.GetContext": "JsonApiDotNetCore.Data.DbContextResolver-1.yml",
+  "JsonApiDotNetCore.Data.DbContextResolver`1.GetDbSet``1": "JsonApiDotNetCore.Data.DbContextResolver-1.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`1": "JsonApiDotNetCore.Data.DefaultEntityRepository-1.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`1.#ctor(Microsoft.Extensions.Logging.ILoggerFactory,JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Data.DefaultEntityRepository-1.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.#ctor(Microsoft.Extensions.Logging.ILoggerFactory,JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.CountAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.CreateAsync(`0)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.DeleteAsync(`1)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.Filter(System.Linq.IQueryable{`0},JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.FirstOrDefaultAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.Get": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.GetAndIncludeAsync(`1,System.String)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.GetAsync(`1)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.Include(System.Linq.IQueryable{`0},System.String)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.PageAsync(System.Linq.IQueryable{`0},System.Int32,System.Int32)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.Sort(System.Linq.IQueryable{`0},System.Collections.Generic.List{JsonApiDotNetCore.Internal.Query.SortQuery})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.ToListAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.UpdateAsync(`1,`0)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.DefaultEntityRepository`2.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.IDbContextResolver": "JsonApiDotNetCore.Data.IDbContextResolver.yml",
+  "JsonApiDotNetCore.Data.IDbContextResolver.GetContext": "JsonApiDotNetCore.Data.IDbContextResolver.yml",
+  "JsonApiDotNetCore.Data.IDbContextResolver.GetDbSet``1": "JsonApiDotNetCore.Data.IDbContextResolver.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`1": "JsonApiDotNetCore.Data.IEntityReadRepository-1.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.CountAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.Filter(System.Linq.IQueryable{`0},JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.FirstOrDefaultAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.Get": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.GetAndIncludeAsync(`1,System.String)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.GetAsync(`1)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.Include(System.Linq.IQueryable{`0},System.String)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.PageAsync(System.Linq.IQueryable{`0},System.Int32,System.Int32)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.Sort(System.Linq.IQueryable{`0},System.Collections.Generic.List{JsonApiDotNetCore.Internal.Query.SortQuery})": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityReadRepository`2.ToListAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityRepository`1": "JsonApiDotNetCore.Data.IEntityRepository-1.yml",
+  "JsonApiDotNetCore.Data.IEntityRepository`2": "JsonApiDotNetCore.Data.IEntityRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityWriteRepository`1": "JsonApiDotNetCore.Data.IEntityWriteRepository-1.yml",
+  "JsonApiDotNetCore.Data.IEntityWriteRepository`2": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityWriteRepository`2.CreateAsync(`0)": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityWriteRepository`2.DeleteAsync(`1)": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityWriteRepository`2.UpdateAsync(`1,`0)": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml",
+  "JsonApiDotNetCore.Data.IEntityWriteRepository`2.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml",
+  "JsonApiDotNetCore.Extensions": "JsonApiDotNetCore.Extensions.yml",
+  "JsonApiDotNetCore.Extensions.DbContextExtensions": "JsonApiDotNetCore.Extensions.DbContextExtensions.yml",
+  "JsonApiDotNetCore.Extensions.DbContextExtensions.GetDbSet``1(Microsoft.EntityFrameworkCore.DbContext)": "JsonApiDotNetCore.Extensions.DbContextExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IApplicationBuilderExtensions": "JsonApiDotNetCore.Extensions.IApplicationBuilderExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IApplicationBuilderExtensions.UseJsonApi(Microsoft.AspNetCore.Builder.IApplicationBuilder,System.Boolean)": "JsonApiDotNetCore.Extensions.IApplicationBuilderExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.Filter``1(System.Linq.IQueryable{``0},JsonApiDotNetCore.Internal.Query.AttrFilterQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.Filter``1(System.Linq.IQueryable{``0},JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.Filter``1(System.Linq.IQueryable{``0},JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.OrderBy``1(System.Linq.IQueryable{``0},System.String)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.OrderByDescending``1(System.Linq.IQueryable{``0},System.String)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.PageForward``1(System.Linq.IQueryable{``0},System.Int32,System.Int32)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.Select``1(System.Linq.IQueryable{``0},System.Collections.Generic.List{System.String})": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.Sort``1(System.Linq.IOrderedQueryable{``0},JsonApiDotNetCore.Internal.Query.SortQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.Sort``1(System.Linq.IQueryable{``0},JsonApiDotNetCore.Internal.Query.SortQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.Sort``1(System.Linq.IQueryable{``0},System.Collections.Generic.List{JsonApiDotNetCore.Internal.Query.SortQuery})": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.ThenBy``1(System.Linq.IOrderedQueryable{``0},System.String)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IQueryableExtensions.ThenByDescending``1(System.Linq.IOrderedQueryable{``0},System.String)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApi(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{JsonApiDotNetCore.Configuration.JsonApiOptions},Microsoft.Extensions.DependencyInjection.IMvcBuilder)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApi``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApi``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{JsonApiDotNetCore.Configuration.JsonApiOptions})": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApi``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{JsonApiDotNetCore.Configuration.JsonApiOptions},Microsoft.Extensions.DependencyInjection.IMvcBuilder)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApiInternals(Microsoft.Extensions.DependencyInjection.IServiceCollection,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApiInternals``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
+  "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.SerializeAsJsonApi(Microsoft.AspNetCore.Mvc.MvcOptions,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
+  "JsonApiDotNetCore.Extensions.JObjectExtensions": "JsonApiDotNetCore.Extensions.JObjectExtensions.yml",
+  "JsonApiDotNetCore.Extensions.JObjectExtensions.TryParse``2(Newtonsoft.Json.Linq.JObject,Newtonsoft.Json.Schema.JSchema,JsonApiDotNetCore.Models.Pointers.Pointer{``1}@)": "JsonApiDotNetCore.Extensions.JObjectExtensions.yml",
+  "JsonApiDotNetCore.Extensions.StringExtensions": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
+  "JsonApiDotNetCore.Extensions.StringExtensions.Dasherize(System.String)": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
+  "JsonApiDotNetCore.Extensions.StringExtensions.ToProperCase(System.String)": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
+  "JsonApiDotNetCore.Formatters": "JsonApiDotNetCore.Formatters.yml",
+  "JsonApiDotNetCore.Formatters.IJsonApiReader": "JsonApiDotNetCore.Formatters.IJsonApiReader.yml",
+  "JsonApiDotNetCore.Formatters.IJsonApiReader.ReadAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext)": "JsonApiDotNetCore.Formatters.IJsonApiReader.yml",
+  "JsonApiDotNetCore.Formatters.IJsonApiWriter": "JsonApiDotNetCore.Formatters.IJsonApiWriter.yml",
+  "JsonApiDotNetCore.Formatters.IJsonApiWriter.WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext)": "JsonApiDotNetCore.Formatters.IJsonApiWriter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiInputFormatter": "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.CanRead(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext)": "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.ReadAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext)": "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter": "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.CanWriteResult(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext)": "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext)": "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiReader": "JsonApiDotNetCore.Formatters.JsonApiReader.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiReader.#ctor(JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Services.IJsonApiContext,Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Formatters.JsonApiReader.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiReader.ReadAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext)": "JsonApiDotNetCore.Formatters.JsonApiReader.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiWriter": "JsonApiDotNetCore.Formatters.JsonApiWriter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiWriter.#ctor(JsonApiDotNetCore.Serialization.IJsonApiSerializer,Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Formatters.JsonApiWriter.yml",
+  "JsonApiDotNetCore.Formatters.JsonApiWriter.WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext)": "JsonApiDotNetCore.Formatters.JsonApiWriter.yml",
+  "JsonApiDotNetCore.Internal": "JsonApiDotNetCore.Internal.yml",
+  "JsonApiDotNetCore.Internal.Constants": "JsonApiDotNetCore.Internal.Constants.yml",
+  "JsonApiDotNetCore.Internal.Constants.AcceptHeader": "JsonApiDotNetCore.Internal.Constants.yml",
+  "JsonApiDotNetCore.Internal.Constants.ContentType": "JsonApiDotNetCore.Internal.Constants.yml",
+  "JsonApiDotNetCore.Internal.ContextEntity": "JsonApiDotNetCore.Internal.ContextEntity.yml",
+  "JsonApiDotNetCore.Internal.ContextEntity.Attributes": "JsonApiDotNetCore.Internal.ContextEntity.yml",
+  "JsonApiDotNetCore.Internal.ContextEntity.EntityName": "JsonApiDotNetCore.Internal.ContextEntity.yml",
+  "JsonApiDotNetCore.Internal.ContextEntity.EntityType": "JsonApiDotNetCore.Internal.ContextEntity.yml",
+  "JsonApiDotNetCore.Internal.ContextEntity.IdentityType": "JsonApiDotNetCore.Internal.ContextEntity.yml",
+  "JsonApiDotNetCore.Internal.ContextEntity.Links": "JsonApiDotNetCore.Internal.ContextEntity.yml",
+  "JsonApiDotNetCore.Internal.ContextEntity.Relationships": "JsonApiDotNetCore.Internal.ContextEntity.yml",
+  "JsonApiDotNetCore.Internal.ContextGraph": "JsonApiDotNetCore.Internal.ContextGraph.yml",
+  "JsonApiDotNetCore.Internal.ContextGraph.#ctor": "JsonApiDotNetCore.Internal.ContextGraph.yml",
+  "JsonApiDotNetCore.Internal.ContextGraph.#ctor(System.Collections.Generic.List{JsonApiDotNetCore.Internal.ContextEntity},System.Boolean)": "JsonApiDotNetCore.Internal.ContextGraph.yml",
+  "JsonApiDotNetCore.Internal.ContextGraph.GetContextEntity(System.String)": "JsonApiDotNetCore.Internal.ContextGraph.yml",
+  "JsonApiDotNetCore.Internal.ContextGraph.GetContextEntity(System.Type)": "JsonApiDotNetCore.Internal.ContextGraph.yml",
+  "JsonApiDotNetCore.Internal.ContextGraph.GetRelationship``1(``0,System.String)": "JsonApiDotNetCore.Internal.ContextGraph.yml",
+  "JsonApiDotNetCore.Internal.ContextGraph.GetRelationshipName``1(System.String)": "JsonApiDotNetCore.Internal.ContextGraph.yml",
+  "JsonApiDotNetCore.Internal.ContextGraph.UsesDbContext": "JsonApiDotNetCore.Internal.ContextGraph.yml",
+  "JsonApiDotNetCore.Internal.DasherizedRoutingConvention": "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.yml",
+  "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.#ctor(System.String)": "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.yml",
+  "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModel)": "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.yml",
+  "JsonApiDotNetCore.Internal.Error": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor(System.Int32,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor(System.Int32,System.String,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor(System.String,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor(System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.Detail": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.Status": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.StatusCode": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.Title": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.ErrorCollection": "JsonApiDotNetCore.Internal.ErrorCollection.yml",
+  "JsonApiDotNetCore.Internal.ErrorCollection.#ctor": "JsonApiDotNetCore.Internal.ErrorCollection.yml",
+  "JsonApiDotNetCore.Internal.ErrorCollection.Add(JsonApiDotNetCore.Internal.Error)": "JsonApiDotNetCore.Internal.ErrorCollection.yml",
+  "JsonApiDotNetCore.Internal.ErrorCollection.Errors": "JsonApiDotNetCore.Internal.ErrorCollection.yml",
+  "JsonApiDotNetCore.Internal.ErrorCollection.GetJson": "JsonApiDotNetCore.Internal.ErrorCollection.yml",
+  "JsonApiDotNetCore.Internal.Generics": "JsonApiDotNetCore.Internal.Generics.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessor`1": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-1.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessor`1.#ctor(JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-1.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.#ctor(JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.SetRelationships(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.#ctor(System.IServiceProvider)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.GetProcessor``1(System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.GetProcessor``1(System.Type,System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.Generics.IGenericProcessor": "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.yml",
+  "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.SetRelationships(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.yml",
+  "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.yml",
+  "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory": "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.GetProcessor``1(System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.GetProcessor``1(System.Type,System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.IContextGraph": "JsonApiDotNetCore.Internal.IContextGraph.yml",
+  "JsonApiDotNetCore.Internal.IContextGraph.GetContextEntity(System.String)": "JsonApiDotNetCore.Internal.IContextGraph.yml",
+  "JsonApiDotNetCore.Internal.IContextGraph.GetContextEntity(System.Type)": "JsonApiDotNetCore.Internal.IContextGraph.yml",
+  "JsonApiDotNetCore.Internal.IContextGraph.GetRelationship``1(``0,System.String)": "JsonApiDotNetCore.Internal.IContextGraph.yml",
+  "JsonApiDotNetCore.Internal.IContextGraph.GetRelationshipName``1(System.String)": "JsonApiDotNetCore.Internal.IContextGraph.yml",
+  "JsonApiDotNetCore.Internal.IContextGraph.UsesDbContext": "JsonApiDotNetCore.Internal.IContextGraph.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(JsonApiDotNetCore.Internal.Error)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(JsonApiDotNetCore.Internal.ErrorCollection)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String,System.Exception)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.GetError": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.GetStatusCode": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiExceptionFactory": "JsonApiDotNetCore.Internal.JsonApiExceptionFactory.yml",
+  "JsonApiDotNetCore.Internal.JsonApiExceptionFactory.GetException(System.Exception)": "JsonApiDotNetCore.Internal.JsonApiExceptionFactory.yml",
+  "JsonApiDotNetCore.Internal.JsonApiRouteHandler": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml",
+  "JsonApiDotNetCore.Internal.JsonApiRouteHandler.#ctor(Microsoft.AspNetCore.Mvc.Infrastructure.IActionInvokerFactory,Microsoft.AspNetCore.Mvc.Infrastructure.IActionSelector)": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml",
+  "JsonApiDotNetCore.Internal.JsonApiRouteHandler.#ctor(Microsoft.AspNetCore.Mvc.Infrastructure.IActionInvokerFactory,Microsoft.AspNetCore.Mvc.Infrastructure.IActionSelector,Microsoft.AspNetCore.Mvc.Infrastructure.IActionContextAccessor)": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml",
+  "JsonApiDotNetCore.Internal.JsonApiRouteHandler.GetVirtualPath(Microsoft.AspNetCore.Routing.VirtualPathContext)": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml",
+  "JsonApiDotNetCore.Internal.JsonApiRouteHandler.RouteAsync(Microsoft.AspNetCore.Routing.RouteContext)": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml",
+  "JsonApiDotNetCore.Internal.PageManager": "JsonApiDotNetCore.Internal.PageManager.yml",
+  "JsonApiDotNetCore.Internal.PageManager.CurrentPage": "JsonApiDotNetCore.Internal.PageManager.yml",
+  "JsonApiDotNetCore.Internal.PageManager.DefaultPageSize": "JsonApiDotNetCore.Internal.PageManager.yml",
+  "JsonApiDotNetCore.Internal.PageManager.GetPageLinks(JsonApiDotNetCore.Builders.LinkBuilder)": "JsonApiDotNetCore.Internal.PageManager.yml",
+  "JsonApiDotNetCore.Internal.PageManager.IsPaginated": "JsonApiDotNetCore.Internal.PageManager.yml",
+  "JsonApiDotNetCore.Internal.PageManager.PageSize": "JsonApiDotNetCore.Internal.PageManager.yml",
+  "JsonApiDotNetCore.Internal.PageManager.TotalPages": "JsonApiDotNetCore.Internal.PageManager.yml",
+  "JsonApiDotNetCore.Internal.PageManager.TotalRecords": "JsonApiDotNetCore.Internal.PageManager.yml",
+  "JsonApiDotNetCore.Internal.Query": "JsonApiDotNetCore.Internal.Query.yml",
+  "JsonApiDotNetCore.Internal.Query.AttrFilterQuery": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.FilteredAttribute": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.FilterOperation": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.PropertyValue": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.BaseFilterQuery": "JsonApiDotNetCore.Internal.Query.BaseFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.BaseFilterQuery.GetFilterOperation(System.String)": "JsonApiDotNetCore.Internal.Query.BaseFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterOperations": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterOperations.eq": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterOperations.ge": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterOperations.gt": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterOperations.le": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterOperations.like": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterOperations.lt": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterQuery": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterQuery.#ctor(System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterQuery.Attribute": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterQuery.IsAttributeOfRelationship": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterQuery.Key": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterQuery.Operation": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.FilterQuery.Value": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.PageQuery": "JsonApiDotNetCore.Internal.Query.PageQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.PageQuery.PageOffset": "JsonApiDotNetCore.Internal.Query.PageQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.PageQuery.PageSize": "JsonApiDotNetCore.Internal.Query.PageQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.QuerySet": "JsonApiDotNetCore.Internal.Query.QuerySet.yml",
+  "JsonApiDotNetCore.Internal.Query.QuerySet.Fields": "JsonApiDotNetCore.Internal.Query.QuerySet.yml",
+  "JsonApiDotNetCore.Internal.Query.QuerySet.Filters": "JsonApiDotNetCore.Internal.Query.QuerySet.yml",
+  "JsonApiDotNetCore.Internal.Query.QuerySet.IncludedRelationships": "JsonApiDotNetCore.Internal.Query.QuerySet.yml",
+  "JsonApiDotNetCore.Internal.Query.QuerySet.PageQuery": "JsonApiDotNetCore.Internal.Query.QuerySet.yml",
+  "JsonApiDotNetCore.Internal.Query.QuerySet.SortParameters": "JsonApiDotNetCore.Internal.Query.QuerySet.yml",
+  "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.FilteredAttribute": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.FilteredRelationship": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.FilterOperation": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.PropertyValue": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.SortDirection": "JsonApiDotNetCore.Internal.Query.SortDirection.yml",
+  "JsonApiDotNetCore.Internal.Query.SortDirection.Ascending": "JsonApiDotNetCore.Internal.Query.SortDirection.yml",
+  "JsonApiDotNetCore.Internal.Query.SortDirection.Descending": "JsonApiDotNetCore.Internal.Query.SortDirection.yml",
+  "JsonApiDotNetCore.Internal.Query.SortQuery": "JsonApiDotNetCore.Internal.Query.SortQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.SortQuery.#ctor(JsonApiDotNetCore.Internal.Query.SortDirection,JsonApiDotNetCore.Models.AttrAttribute)": "JsonApiDotNetCore.Internal.Query.SortQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.SortQuery.Direction": "JsonApiDotNetCore.Internal.Query.SortQuery.yml",
+  "JsonApiDotNetCore.Internal.Query.SortQuery.SortedAttribute": "JsonApiDotNetCore.Internal.Query.SortQuery.yml",
+  "JsonApiDotNetCore.Internal.TypeHelper": "JsonApiDotNetCore.Internal.TypeHelper.yml",
+  "JsonApiDotNetCore.Internal.TypeHelper.ConvertType(System.Object,System.Type)": "JsonApiDotNetCore.Internal.TypeHelper.yml",
+  "JsonApiDotNetCore.Internal.TypeHelper.ConvertType``1(System.Object)": "JsonApiDotNetCore.Internal.TypeHelper.yml",
+  "JsonApiDotNetCore.Middleware": "JsonApiDotNetCore.Middleware.yml",
+  "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter": "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.yml",
+  "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.#ctor(Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.yml",
+  "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.OnException(Microsoft.AspNetCore.Mvc.Filters.ExceptionContext)": "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.yml",
+  "JsonApiDotNetCore.Middleware.RequestMiddleware": "JsonApiDotNetCore.Middleware.RequestMiddleware.yml",
+  "JsonApiDotNetCore.Middleware.RequestMiddleware.#ctor(Microsoft.AspNetCore.Http.RequestDelegate)": "JsonApiDotNetCore.Middleware.RequestMiddleware.yml",
+  "JsonApiDotNetCore.Middleware.RequestMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext)": "JsonApiDotNetCore.Middleware.RequestMiddleware.yml",
+  "JsonApiDotNetCore.Models": "JsonApiDotNetCore.Models.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.#ctor(System.String,System.Boolean,System.Boolean,System.Boolean)": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.GetValue(System.Object)": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.InternalAttributeName": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.IsFilterable": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.IsImmutable": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.IsSortable": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.PublicAttributeName": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.SetValue(System.Object,System.Object)": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.Document": "JsonApiDotNetCore.Models.Document.yml",
+  "JsonApiDotNetCore.Models.Document.Data": "JsonApiDotNetCore.Models.Document.yml",
+  "JsonApiDotNetCore.Models.DocumentBase": "JsonApiDotNetCore.Models.DocumentBase.yml",
+  "JsonApiDotNetCore.Models.DocumentBase.Included": "JsonApiDotNetCore.Models.DocumentBase.yml",
+  "JsonApiDotNetCore.Models.DocumentBase.Links": "JsonApiDotNetCore.Models.DocumentBase.yml",
+  "JsonApiDotNetCore.Models.DocumentBase.Meta": "JsonApiDotNetCore.Models.DocumentBase.yml",
+  "JsonApiDotNetCore.Models.DocumentData": "JsonApiDotNetCore.Models.DocumentData.yml",
+  "JsonApiDotNetCore.Models.Documents": "JsonApiDotNetCore.Models.Documents.yml",
+  "JsonApiDotNetCore.Models.Documents.Data": "JsonApiDotNetCore.Models.Documents.yml",
+  "JsonApiDotNetCore.Models.HasManyAttribute": "JsonApiDotNetCore.Models.HasManyAttribute.yml",
+  "JsonApiDotNetCore.Models.HasManyAttribute.#ctor(System.String,JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.HasManyAttribute.yml",
+  "JsonApiDotNetCore.Models.HasManyAttribute.SetValue(System.Object,System.Object)": "JsonApiDotNetCore.Models.HasManyAttribute.yml",
+  "JsonApiDotNetCore.Models.HasOneAttribute": "JsonApiDotNetCore.Models.HasOneAttribute.yml",
+  "JsonApiDotNetCore.Models.HasOneAttribute.#ctor(System.String,JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.HasOneAttribute.yml",
+  "JsonApiDotNetCore.Models.HasOneAttribute.SetValue(System.Object,System.Object)": "JsonApiDotNetCore.Models.HasOneAttribute.yml",
+  "JsonApiDotNetCore.Models.Identifiable": "JsonApiDotNetCore.Models.Identifiable.yml",
+  "JsonApiDotNetCore.Models.Identifiable`1": "JsonApiDotNetCore.Models.Identifiable-1.yml",
+  "JsonApiDotNetCore.Models.Identifiable`1.GetConcreteId(System.String)": "JsonApiDotNetCore.Models.Identifiable-1.yml",
+  "JsonApiDotNetCore.Models.Identifiable`1.GetStringId(System.Object)": "JsonApiDotNetCore.Models.Identifiable-1.yml",
+  "JsonApiDotNetCore.Models.Identifiable`1.Id": "JsonApiDotNetCore.Models.Identifiable-1.yml",
+  "JsonApiDotNetCore.Models.Identifiable`1.StringId": "JsonApiDotNetCore.Models.Identifiable-1.yml",
+  "JsonApiDotNetCore.Models.IHasMeta": "JsonApiDotNetCore.Models.IHasMeta.yml",
+  "JsonApiDotNetCore.Models.IHasMeta.GetMeta(JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Models.IHasMeta.yml",
+  "JsonApiDotNetCore.Models.IIdentifiable": "JsonApiDotNetCore.Models.IIdentifiable.yml",
+  "JsonApiDotNetCore.Models.IIdentifiable.StringId": "JsonApiDotNetCore.Models.IIdentifiable.yml",
+  "JsonApiDotNetCore.Models.IIdentifiable`1": "JsonApiDotNetCore.Models.IIdentifiable-1.yml",
+  "JsonApiDotNetCore.Models.IIdentifiable`1.Id": "JsonApiDotNetCore.Models.IIdentifiable-1.yml",
+  "JsonApiDotNetCore.Models.JsonApiExtension": "JsonApiDotNetCore.Models.JsonApiExtension.yml",
+  "JsonApiDotNetCore.Models.JsonApiExtension.Operations": "JsonApiDotNetCore.Models.JsonApiExtension.yml",
+  "JsonApiDotNetCore.Models.Link": "JsonApiDotNetCore.Models.Link.yml",
+  "JsonApiDotNetCore.Models.Link.All": "JsonApiDotNetCore.Models.Link.yml",
+  "JsonApiDotNetCore.Models.Link.None": "JsonApiDotNetCore.Models.Link.yml",
+  "JsonApiDotNetCore.Models.Link.Paging": "JsonApiDotNetCore.Models.Link.yml",
+  "JsonApiDotNetCore.Models.Link.Related": "JsonApiDotNetCore.Models.Link.yml",
+  "JsonApiDotNetCore.Models.Link.Self": "JsonApiDotNetCore.Models.Link.yml",
+  "JsonApiDotNetCore.Models.Links": "JsonApiDotNetCore.Models.Links.yml",
+  "JsonApiDotNetCore.Models.Links.Related": "JsonApiDotNetCore.Models.Links.yml",
+  "JsonApiDotNetCore.Models.Links.Self": "JsonApiDotNetCore.Models.Links.yml",
+  "JsonApiDotNetCore.Models.LinksAttribute": "JsonApiDotNetCore.Models.LinksAttribute.yml",
+  "JsonApiDotNetCore.Models.LinksAttribute.#ctor(JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.LinksAttribute.yml",
+  "JsonApiDotNetCore.Models.LinksAttribute.Links": "JsonApiDotNetCore.Models.LinksAttribute.yml",
+  "JsonApiDotNetCore.Models.Operations": "JsonApiDotNetCore.Models.Operations.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation.Data": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation.DataIsList": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation.DataList": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation.DataObject": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation.GetResourceTypeName": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation.Op": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation.Params": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.Operation.Ref": "JsonApiDotNetCore.Models.Operations.Operation.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationCode": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationCode.add": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationCode.get": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationCode.remove": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationCode.replace": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationsDocument": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationsDocument.#ctor": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationsDocument.#ctor(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationsDocument.Operations": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml",
+  "JsonApiDotNetCore.Models.Operations.Params": "JsonApiDotNetCore.Models.Operations.Params.yml",
+  "JsonApiDotNetCore.Models.Operations.Params.Fields": "JsonApiDotNetCore.Models.Operations.Params.yml",
+  "JsonApiDotNetCore.Models.Operations.Params.Filter": "JsonApiDotNetCore.Models.Operations.Params.yml",
+  "JsonApiDotNetCore.Models.Operations.Params.Include": "JsonApiDotNetCore.Models.Operations.Params.yml",
+  "JsonApiDotNetCore.Models.Operations.Params.Page": "JsonApiDotNetCore.Models.Operations.Params.yml",
+  "JsonApiDotNetCore.Models.Operations.Params.Sort": "JsonApiDotNetCore.Models.Operations.Params.yml",
+  "JsonApiDotNetCore.Models.Operations.ResourceReference": "JsonApiDotNetCore.Models.Operations.ResourceReference.yml",
+  "JsonApiDotNetCore.Models.Operations.ResourceReference.Relationship": "JsonApiDotNetCore.Models.Operations.ResourceReference.yml",
+  "JsonApiDotNetCore.Models.Pointers": "JsonApiDotNetCore.Models.Pointers.yml",
+  "JsonApiDotNetCore.Models.Pointers.OperationsPointer": "JsonApiDotNetCore.Models.Pointers.OperationsPointer.yml",
+  "JsonApiDotNetCore.Models.Pointers.OperationsPointer.GetValue(System.Object)": "JsonApiDotNetCore.Models.Pointers.OperationsPointer.yml",
+  "JsonApiDotNetCore.Models.Pointers.Pointer`1": "JsonApiDotNetCore.Models.Pointers.Pointer-1.yml",
+  "JsonApiDotNetCore.Models.Pointers.Pointer`1.GetValue(System.Object)": "JsonApiDotNetCore.Models.Pointers.Pointer-1.yml",
+  "JsonApiDotNetCore.Models.Pointers.Pointer`1.JsonSchema": "JsonApiDotNetCore.Models.Pointers.Pointer-1.yml",
+  "JsonApiDotNetCore.Models.Pointers.Pointer`1.PointerAddress": "JsonApiDotNetCore.Models.Pointers.Pointer-1.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.#ctor(System.String,JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.DocumentLinks": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.Equals(System.Object)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.InternalRelationshipName": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.IsHasMany": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.IsHasOne": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.PublicRelationshipName": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.SetValue(System.Object,System.Object)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.ToString": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.Type": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipData": "JsonApiDotNetCore.Models.RelationshipData.yml",
+  "JsonApiDotNetCore.Models.RelationshipData.ExposedData": "JsonApiDotNetCore.Models.RelationshipData.yml",
+  "JsonApiDotNetCore.Models.RelationshipData.IsHasMany": "JsonApiDotNetCore.Models.RelationshipData.yml",
+  "JsonApiDotNetCore.Models.RelationshipData.Links": "JsonApiDotNetCore.Models.RelationshipData.yml",
+  "JsonApiDotNetCore.Models.RelationshipData.ManyData": "JsonApiDotNetCore.Models.RelationshipData.yml",
+  "JsonApiDotNetCore.Models.RelationshipData.SingleData": "JsonApiDotNetCore.Models.RelationshipData.yml",
+  "JsonApiDotNetCore.Models.ResourceAttribute": "JsonApiDotNetCore.Models.ResourceAttribute.yml",
+  "JsonApiDotNetCore.Models.ResourceAttribute.#ctor(System.String)": "JsonApiDotNetCore.Models.ResourceAttribute.yml",
+  "JsonApiDotNetCore.Models.ResourceAttribute.ResourceName": "JsonApiDotNetCore.Models.ResourceAttribute.yml",
+  "JsonApiDotNetCore.Models.ResourceIdentifierObject": "JsonApiDotNetCore.Models.ResourceIdentifierObject.yml",
+  "JsonApiDotNetCore.Models.ResourceIdentifierObject.Id": "JsonApiDotNetCore.Models.ResourceIdentifierObject.yml",
+  "JsonApiDotNetCore.Models.ResourceIdentifierObject.LocalId": "JsonApiDotNetCore.Models.ResourceIdentifierObject.yml",
+  "JsonApiDotNetCore.Models.ResourceIdentifierObject.Type": "JsonApiDotNetCore.Models.ResourceIdentifierObject.yml",
+  "JsonApiDotNetCore.Models.ResourceObject": "JsonApiDotNetCore.Models.ResourceObject.yml",
+  "JsonApiDotNetCore.Models.ResourceObject.Attributes": "JsonApiDotNetCore.Models.ResourceObject.yml",
+  "JsonApiDotNetCore.Models.ResourceObject.Relationships": "JsonApiDotNetCore.Models.ResourceObject.yml",
+  "JsonApiDotNetCore.Models.RootLinks": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.First": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.Last": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.Next": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.Prev": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.Self": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.ShouldSerializeFirst": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.ShouldSerializeLast": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.ShouldSerializeNext": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.ShouldSerializePrev": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Models.RootLinks.ShouldSerializeSelf": "JsonApiDotNetCore.Models.RootLinks.yml",
+  "JsonApiDotNetCore.Serialization": "JsonApiDotNetCore.Serialization.yml",
+  "JsonApiDotNetCore.Serialization.DasherizedResolver": "JsonApiDotNetCore.Serialization.DasherizedResolver.yml",
+  "JsonApiDotNetCore.Serialization.DasherizedResolver.CreateProperty(System.Reflection.MemberInfo,Newtonsoft.Json.MemberSerialization)": "JsonApiDotNetCore.Serialization.DasherizedResolver.yml",
+  "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.Deserialize(System.String)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.Deserialize``1(System.String)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.DeserializeList``1(System.String)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.DeserializeRelationship(System.String)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.DocumentToObject(JsonApiDotNetCore.Models.DocumentData)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.IJsonApiSerializer": "JsonApiDotNetCore.Serialization.IJsonApiSerializer.yml",
+  "JsonApiDotNetCore.Serialization.IJsonApiSerializer.Serialize(System.Object)": "JsonApiDotNetCore.Serialization.IJsonApiSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiDeSerializer": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(System.String)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize``1(System.String)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.DeserializeList``1(System.String)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.DeserializeRelationship(System.String)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.DocumentToObject(JsonApiDotNetCore.Models.DocumentData)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiSerializer": "JsonApiDotNetCore.Serialization.JsonApiSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiSerializer.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Builders.IDocumentBuilder)": "JsonApiDotNetCore.Serialization.JsonApiSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiSerializer.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Builders.IDocumentBuilder,Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Serialization.JsonApiSerializer.yml",
+  "JsonApiDotNetCore.Serialization.JsonApiSerializer.Serialize(System.Object)": "JsonApiDotNetCore.Serialization.JsonApiSerializer.yml",
+  "JsonApiDotNetCore.Services": "JsonApiDotNetCore.Services.yml",
+  "JsonApiDotNetCore.Services.ControllerContext": "JsonApiDotNetCore.Services.ControllerContext.yml",
+  "JsonApiDotNetCore.Services.ControllerContext.ControllerType": "JsonApiDotNetCore.Services.ControllerContext.yml",
+  "JsonApiDotNetCore.Services.ControllerContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.ControllerContext.yml",
+  "JsonApiDotNetCore.Services.ControllerContext.RequestEntity": "JsonApiDotNetCore.Services.ControllerContext.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`1": "JsonApiDotNetCore.Services.EntityResourceService-1.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Data.IEntityRepository{`0},Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Services.EntityResourceService-1.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Data.IEntityRepository{`0,`1},Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.CreateAsync(`0)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.DeleteAsync(`1)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.GetAsync": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.GetAsync(`1)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.UpdateAsync(`1,`0)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.EntityResourceService`2.UpdateRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Services.EntityResourceService-2.yml",
+  "JsonApiDotNetCore.Services.IControllerContext": "JsonApiDotNetCore.Services.IControllerContext.yml",
+  "JsonApiDotNetCore.Services.IControllerContext.ControllerType": "JsonApiDotNetCore.Services.IControllerContext.yml",
+  "JsonApiDotNetCore.Services.IControllerContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.IControllerContext.yml",
+  "JsonApiDotNetCore.Services.IControllerContext.RequestEntity": "JsonApiDotNetCore.Services.IControllerContext.yml",
+  "JsonApiDotNetCore.Services.ICreateService`1": "JsonApiDotNetCore.Services.ICreateService-1.yml",
+  "JsonApiDotNetCore.Services.ICreateService`2": "JsonApiDotNetCore.Services.ICreateService-2.yml",
+  "JsonApiDotNetCore.Services.ICreateService`2.CreateAsync(`0)": "JsonApiDotNetCore.Services.ICreateService-2.yml",
+  "JsonApiDotNetCore.Services.IDeleteService`1": "JsonApiDotNetCore.Services.IDeleteService-1.yml",
+  "JsonApiDotNetCore.Services.IDeleteService`2": "JsonApiDotNetCore.Services.IDeleteService-2.yml",
+  "JsonApiDotNetCore.Services.IDeleteService`2.DeleteAsync(`1)": "JsonApiDotNetCore.Services.IDeleteService-2.yml",
+  "JsonApiDotNetCore.Services.IGetAllService`1": "JsonApiDotNetCore.Services.IGetAllService-1.yml",
+  "JsonApiDotNetCore.Services.IGetAllService`2": "JsonApiDotNetCore.Services.IGetAllService-2.yml",
+  "JsonApiDotNetCore.Services.IGetAllService`2.GetAsync": "JsonApiDotNetCore.Services.IGetAllService-2.yml",
+  "JsonApiDotNetCore.Services.IGetByIdService`1": "JsonApiDotNetCore.Services.IGetByIdService-1.yml",
+  "JsonApiDotNetCore.Services.IGetByIdService`2": "JsonApiDotNetCore.Services.IGetByIdService-2.yml",
+  "JsonApiDotNetCore.Services.IGetByIdService`2.GetAsync(`1)": "JsonApiDotNetCore.Services.IGetByIdService-2.yml",
+  "JsonApiDotNetCore.Services.IGetRelationshipService`1": "JsonApiDotNetCore.Services.IGetRelationshipService-1.yml",
+  "JsonApiDotNetCore.Services.IGetRelationshipService`2": "JsonApiDotNetCore.Services.IGetRelationshipService-2.yml",
+  "JsonApiDotNetCore.Services.IGetRelationshipService`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Services.IGetRelationshipService-2.yml",
+  "JsonApiDotNetCore.Services.IGetRelationshipsService`1": "JsonApiDotNetCore.Services.IGetRelationshipsService-1.yml",
+  "JsonApiDotNetCore.Services.IGetRelationshipsService`2": "JsonApiDotNetCore.Services.IGetRelationshipsService-2.yml",
+  "JsonApiDotNetCore.Services.IGetRelationshipsService`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Services.IGetRelationshipsService-2.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.ApplyContext``1(System.Object)": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.AttributesToUpdate": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.BasePath": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.ContextGraph": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.ControllerType": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.DocumentMeta": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.GenericProcessorFactory": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.IncludedRelationships": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.IsRelationshipData": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.IsRelationshipPath": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.MetaBuilder": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.Options": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.PageManager": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.QuerySet": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.RelationshipsToUpdate": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.RequestEntity": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IQueryAccessor": "JsonApiDotNetCore.Services.IQueryAccessor.yml",
+  "JsonApiDotNetCore.Services.IQueryAccessor.GetRequired``1(System.String)": "JsonApiDotNetCore.Services.IQueryAccessor.yml",
+  "JsonApiDotNetCore.Services.IQueryAccessor.TryGetValue``1(System.String,``0@)": "JsonApiDotNetCore.Services.IQueryAccessor.yml",
+  "JsonApiDotNetCore.Services.IQueryParser": "JsonApiDotNetCore.Services.IQueryParser.yml",
+  "JsonApiDotNetCore.Services.IQueryParser.Parse(Microsoft.AspNetCore.Http.IQueryCollection)": "JsonApiDotNetCore.Services.IQueryParser.yml",
+  "JsonApiDotNetCore.Services.IRequestMeta": "JsonApiDotNetCore.Services.IRequestMeta.yml",
+  "JsonApiDotNetCore.Services.IRequestMeta.GetMeta": "JsonApiDotNetCore.Services.IRequestMeta.yml",
+  "JsonApiDotNetCore.Services.IResourceCmdService`1": "JsonApiDotNetCore.Services.IResourceCmdService-1.yml",
+  "JsonApiDotNetCore.Services.IResourceCmdService`2": "JsonApiDotNetCore.Services.IResourceCmdService-2.yml",
+  "JsonApiDotNetCore.Services.IResourceQueryService`1": "JsonApiDotNetCore.Services.IResourceQueryService-1.yml",
+  "JsonApiDotNetCore.Services.IResourceQueryService`2": "JsonApiDotNetCore.Services.IResourceQueryService-2.yml",
+  "JsonApiDotNetCore.Services.IResourceService`1": "JsonApiDotNetCore.Services.IResourceService-1.yml",
+  "JsonApiDotNetCore.Services.IResourceService`2": "JsonApiDotNetCore.Services.IResourceService-2.yml",
+  "JsonApiDotNetCore.Services.IUpdateRelationshipService`1": "JsonApiDotNetCore.Services.IUpdateRelationshipService-1.yml",
+  "JsonApiDotNetCore.Services.IUpdateRelationshipService`2": "JsonApiDotNetCore.Services.IUpdateRelationshipService-2.yml",
+  "JsonApiDotNetCore.Services.IUpdateRelationshipService`2.UpdateRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Services.IUpdateRelationshipService-2.yml",
+  "JsonApiDotNetCore.Services.IUpdateService`1": "JsonApiDotNetCore.Services.IUpdateService-1.yml",
+  "JsonApiDotNetCore.Services.IUpdateService`2": "JsonApiDotNetCore.Services.IUpdateService-2.yml",
+  "JsonApiDotNetCore.Services.IUpdateService`2.UpdateAsync(`1,`0)": "JsonApiDotNetCore.Services.IUpdateService-2.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.#ctor(JsonApiDotNetCore.Internal.IContextGraph,Microsoft.AspNetCore.Http.IHttpContextAccessor,JsonApiDotNetCore.Configuration.JsonApiOptions,JsonApiDotNetCore.Builders.IMetaBuilder,JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory,JsonApiDotNetCore.Services.IQueryParser,JsonApiDotNetCore.Services.IControllerContext)": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.ApplyContext``1(System.Object)": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.AttributesToUpdate": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.BasePath": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.ContextGraph": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.ControllerType": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.DocumentMeta": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.GenericProcessorFactory": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.IncludedRelationships": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.IsRelationshipData": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.IsRelationshipPath": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.MetaBuilder": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.Options": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.PageManager": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.QuerySet": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.RelationshipsToUpdate": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.RequestEntity": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.Operations": "JsonApiDotNetCore.Services.Operations.yml",
+  "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateCreateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateGetService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateRemoveService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateReplaceService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.IOperationsProcessor": "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.yml",
+  "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.ProcessAsync(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.yml",
+  "JsonApiDotNetCore.Services.Operations.IOpProcessor": "JsonApiDotNetCore.Services.Operations.IOpProcessor.yml",
+  "JsonApiDotNetCore.Services.Operations.IOpProcessor.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOpProcessor.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.#ctor(JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateCreateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateGetService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateRemoveService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateReplaceService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationsProcessor": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationsProcessor.#ctor(JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver,JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationsProcessor.ProcessAsync(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors": "JsonApiDotNetCore.Services.Operations.Processors.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`1.#ctor(JsonApiDotNetCore.Services.ICreateService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`2.#ctor(JsonApiDotNetCore.Services.ICreateService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IGetAllService{`0,System.Int32},JsonApiDotNetCore.Services.IGetByIdService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IGetAllService{`0,`1},JsonApiDotNetCore.Services.IGetByIdService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.IReplaceOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IReplaceOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.IReplaceOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IReplaceOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IDeleteService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IDeleteService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IUpdateService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IUpdateService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.QueryAccessor": "JsonApiDotNetCore.Services.QueryAccessor.yml",
+  "JsonApiDotNetCore.Services.QueryAccessor.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,Microsoft.Extensions.Logging.ILogger{JsonApiDotNetCore.Services.QueryAccessor})": "JsonApiDotNetCore.Services.QueryAccessor.yml",
+  "JsonApiDotNetCore.Services.QueryAccessor.GetRequired``1(System.String)": "JsonApiDotNetCore.Services.QueryAccessor.yml",
+  "JsonApiDotNetCore.Services.QueryAccessor.TryGetValue``1(System.String,``0@)": "JsonApiDotNetCore.Services.QueryAccessor.yml",
+  "JsonApiDotNetCore.Services.QueryParser": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.#ctor(JsonApiDotNetCore.Services.IControllerContext,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.GetAttribute(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.Parse(Microsoft.AspNetCore.Http.IQueryCollection)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.ParseFieldsQuery(System.String,System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.ParseFilterOperation(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.ParseFilterQuery(System.String,System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.ParseIncludedRelationships(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.ParsePageQuery(JsonApiDotNetCore.Internal.Query.PageQuery,System.String,System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.QueryParser.ParseSortParameters(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml"
+}
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/api/index.md b/src/JsonApiDotNetCore/api/index.md
new file mode 100644
index 0000000000..78dc9c0057
--- /dev/null
+++ b/src/JsonApiDotNetCore/api/index.md
@@ -0,0 +1,2 @@
+# PLACEHOLDER
+TODO: Add .NET projects to the *src* folder and run `docfx` to generate **REAL** *API Documentation*!
diff --git a/src/JsonApiDotNetCore/articles/intro.md b/src/JsonApiDotNetCore/articles/intro.md
new file mode 100644
index 0000000000..c0478cedea
--- /dev/null
+++ b/src/JsonApiDotNetCore/articles/intro.md
@@ -0,0 +1 @@
+# Add your introductions here!
diff --git a/src/JsonApiDotNetCore/articles/toc.yml b/src/JsonApiDotNetCore/articles/toc.yml
new file mode 100644
index 0000000000..ff89ef1fe0
--- /dev/null
+++ b/src/JsonApiDotNetCore/articles/toc.yml
@@ -0,0 +1,2 @@
+- name: Introduction
+  href: intro.md
diff --git a/src/JsonApiDotNetCore/docfx.json b/src/JsonApiDotNetCore/docfx.json
new file mode 100644
index 0000000000..5c46dcbd88
--- /dev/null
+++ b/src/JsonApiDotNetCore/docfx.json
@@ -0,0 +1,52 @@
+{
+    "metadata": [
+        {
+            "src": [
+                {
+                    "files": [ "**.csproj" ],
+                    "src": "C:\\Users\\jnance\\dev\\json-api-dotnet-core\\src\\JsonApiDotNetCore"
+                }
+            ],
+            "dest": "api",
+            "disableGitFeatures": false,
+            "properties": {
+                "targetFramework": "netstandard2.0"
+            }
+        }
+    ],
+    "build": {
+        "content": [
+            {
+                "files": [ "api/**.yml", "api/index.md" ]
+            },
+            {
+                "files": [
+                    "articles/**.md",
+                    "articles/**/toc.yml",
+                    "toc.yml",
+                    "*.md"
+                ]
+            }
+        ],
+        "resource": [
+            {
+                "files": [ "images/**" ]
+            }
+        ],
+        "overwrite": [
+            {
+                "files": [ "apidoc/**.md" ],
+                "exclude": [ "obj/**", "_site/**" ]
+            }
+        ],
+        "dest": "_site",
+        "globalMetadataFiles": [],
+        "fileMetadataFiles": [],
+        "template": [ "default" ],
+        "postProcessors": [],
+        "noLangKeyword": false,
+        "keepFileLink": false,
+        "cleanupCacheHistory": false,
+        "disableGitFeatures": false
+    }
+}
diff --git a/src/JsonApiDotNetCore/index.md b/src/JsonApiDotNetCore/index.md
new file mode 100644
index 0000000000..3ae2506361
--- /dev/null
+++ b/src/JsonApiDotNetCore/index.md
@@ -0,0 +1,4 @@
+# This is the **HOMEPAGE**.
+Refer to [Markdown](http://daringfireball.net/projects/markdown/) for how to write markdown files.
+## Quick Start Notes:
+1. Add images to the *images* folder if the file is referencing an image.
diff --git a/src/JsonApiDotNetCore/toc.yml b/src/JsonApiDotNetCore/toc.yml
new file mode 100644
index 0000000000..59f8010471
--- /dev/null
+++ b/src/JsonApiDotNetCore/toc.yml
@@ -0,0 +1,5 @@
+- name: Articles
+  href: articles/
+- name: Api Documentation
+  href: api/
+  homepage: api/index.md

From 9719f7496571e139521b0fcb047442b1775f4dce Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 25 Mar 2018 08:36:44 -0500
Subject: [PATCH 101/227] support bulk add transaction

- rename replace to update
- rollback failed transactions
---
 Directory.Build.props                         |   9 +-
 .../OperationsExample/Data/AppDbContext.cs    |   1 +
 .../20170827234334_AddArticles.Designer.cs    |  33 ---
 .../Migrations/20170827234334_AddArticles.cs  |  32 ---
 ...80325130426_ArticlesAndAuthors.Designer.cs |  61 +++++
 .../20180325130426_ArticlesAndAuthors.cs      |  60 +++++
 .../Migrations/AppDbContextModelSnapshot.cs   |  32 ++-
 .../OperationsExample/Models/Article.cs       |   8 +-
 .../OperationsExample/Models/Author.cs        |  14 ++
 .../OperationsExample.csproj                  |   1 +
 src/Examples/OperationsExample/Program.cs     |  21 +-
 .../OperationsExample/appsettings.json        |  22 +-
 .../Controllers/JsonApiControllerMixin.cs     |   9 +-
 .../JsonApiOperationsController.cs            |   2 +
 .../Data/DbContextResolver.cs                 |   2 +-
 .../IServiceCollectionExtensions.cs           |   6 +-
 .../Extensions/JObjectExtensions.cs           |   6 +-
 .../Models/Operations/OperationCode.cs        |   6 +-
 .../Models/Pointers/OperationsPointer.cs      |  10 +-
 .../Models/Pointers/Pointer.cs                |   2 +-
 .../Serialization/JsonApiDeSerializer.cs      |  12 +-
 .../Serialization/JsonApiSerializer.cs        |   7 +-
 .../Services/IJsonApiContext.cs               |   1 +
 .../Services/JsonApiContext.cs                |   1 +
 .../Operations/OperationProcessorResolver.cs  |  20 +-
 .../Operations/OperationsProcessor.cs         |  51 ++--
 .../Processors/CreateOpProcessor.cs           |   4 +
 .../Processors/RemoveOpProcessor.cs           |   7 +-
 ...aceOpProcessor.cs => UpdateOpProcessor.cs} |  20 +-
 src/JsonApiDotNetCore/api/.manifest           |  30 +--
 .../ReplaceTests.cs => Update/UpdateTests.cs} | 224 +++++++++---------
 .../Operations/OperationsProcessorTests.cs    |   4 +-
 32 files changed, 408 insertions(+), 310 deletions(-)
 delete mode 100755 src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs
 delete mode 100755 src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs
 create mode 100644 src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.Designer.cs
 create mode 100644 src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.cs
 create mode 100644 src/Examples/OperationsExample/Models/Author.cs
 rename src/JsonApiDotNetCore/Services/Operations/Processors/{ReplaceOpProcessor.cs => UpdateOpProcessor.cs} (79%)
 rename test/OperationsExampleTests/{Replace/ReplaceTests.cs => Update/UpdateTests.cs} (93%)

diff --git a/Directory.Build.props b/Directory.Build.props
index cc81f65974..346835dd6c 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,5 +1,5 @@
 <Project>
- 
+
   <PropertyGroup>
     <NetCoreAppVersion>netcoreapp2.0</NetCoreAppVersion>
     <NetStandardVersion>netstandard2.0</NetStandardVersion>
@@ -10,7 +10,6 @@
     <MicrosoftConfigurationVersion>2.0.0</MicrosoftConfigurationVersion>
     <MicrosoftOptionsVersion>2.0.0</MicrosoftOptionsVersion>
 
-
     <EFCoreVersion>2.0.1</EFCoreVersion>
     <EFCoreToolsVersion>2.0.1</EFCoreToolsVersion>
 
@@ -19,8 +18,8 @@
 
     <TuplesVersion>4.4.0</TuplesVersion>
   </PropertyGroup>
- 
- <!-- Test Project Dependencies -->
+
+  <!-- Test Project Dependencies -->
   <PropertyGroup>
     <TestSdkVersion>15.3.0-preview-20170427-09</TestSdkVersion>
     <TestHostVersion>1.1.2</TestHostVersion>
@@ -28,5 +27,5 @@
     <BogusVersion>15.0.3</BogusVersion>
     <MoqVersion>4.7.99</MoqVersion>
   </PropertyGroup>
- 
+
 </Project>
diff --git a/src/Examples/OperationsExample/Data/AppDbContext.cs b/src/Examples/OperationsExample/Data/AppDbContext.cs
index d00bfe4765..3d5b3e2e54 100644
--- a/src/Examples/OperationsExample/Data/AppDbContext.cs
+++ b/src/Examples/OperationsExample/Data/AppDbContext.cs
@@ -10,5 +10,6 @@ public AppDbContext(DbContextOptions<AppDbContext> options)
         { }
 
         public DbSet<Article> Articles { get; set; }
+        public DbSet<Author> Authors { get; set; }
     }
 }
diff --git a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs b/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs
deleted file mode 100755
index 10f16d49cd..0000000000
--- a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using OperationsExample.Data;
-
-namespace OperationsExample.Migrations
-{
-    [DbContext(typeof(AppDbContext))]
-    [Migration("20170827234334_AddArticles")]
-    partial class AddArticles
-    {
-        protected override void BuildTargetModel(ModelBuilder modelBuilder)
-        {
-            modelBuilder
-                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "1.1.2");
-
-            modelBuilder.Entity("OperationsExample.Models.Article", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("Name");
-
-                    b.HasKey("Id");
-
-                    b.ToTable("Articles");
-                });
-        }
-    }
-}
diff --git a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs b/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs
deleted file mode 100755
index 308e6f78f5..0000000000
--- a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Metadata;
-
-namespace OperationsExample.Migrations
-{
-    public partial class AddArticles : Migration
-    {
-        protected override void Up(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.CreateTable(
-                name: "Articles",
-                columns: table => new
-                {
-                    Id = table.Column<int>(nullable: false)
-                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
-                    Name = table.Column<string>(nullable: true)
-                },
-                constraints: table =>
-                {
-                    table.PrimaryKey("PK_Articles", x => x.Id);
-                });
-        }
-
-        protected override void Down(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.DropTable(
-                name: "Articles");
-        }
-    }
-}
diff --git a/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.Designer.cs b/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.Designer.cs
new file mode 100644
index 0000000000..e9934cb776
--- /dev/null
+++ b/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.Designer.cs
@@ -0,0 +1,61 @@
+// <auto-generated />
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage;
+using Microsoft.EntityFrameworkCore.Storage.Internal;
+using OperationsExample.Data;
+using System;
+
+namespace OperationsExample.Migrations
+{
+    [DbContext(typeof(AppDbContext))]
+    [Migration("20180325130426_ArticlesAndAuthors")]
+    partial class ArticlesAndAuthors
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
+                .HasAnnotation("ProductVersion", "2.0.1-rtm-125");
+
+            modelBuilder.Entity("OperationsExample.Models.Article", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<int?>("AuthorId");
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("AuthorId");
+
+                    b.ToTable("Articles");
+                });
+
+            modelBuilder.Entity("OperationsExample.Models.Author", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Authors");
+                });
+
+            modelBuilder.Entity("OperationsExample.Models.Article", b =>
+                {
+                    b.HasOne("OperationsExample.Models.Author", "Author")
+                        .WithMany("Articles")
+                        .HasForeignKey("AuthorId");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.cs b/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.cs
new file mode 100644
index 0000000000..1a0d5e309a
--- /dev/null
+++ b/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.cs
@@ -0,0 +1,60 @@
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using System;
+using System.Collections.Generic;
+
+namespace OperationsExample.Migrations
+{
+    public partial class ArticlesAndAuthors : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.CreateTable(
+                name: "Authors",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
+                    Name = table.Column<string>(nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Authors", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Articles",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
+                    AuthorId = table.Column<int>(nullable: true),
+                    Name = table.Column<string>(nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Articles", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Articles_Authors_AuthorId",
+                        column: x => x.AuthorId,
+                        principalTable: "Authors",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Articles_AuthorId",
+                table: "Articles",
+                column: "AuthorId");
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "Articles");
+
+            migrationBuilder.DropTable(
+                name: "Authors");
+        }
+    }
+}
diff --git a/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs b/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs
index 547bbbf2cf..b4c9a0ebba 100755
--- a/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs
+++ b/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs
@@ -1,9 +1,12 @@
-using System;
+// <auto-generated />
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.Infrastructure;
 using Microsoft.EntityFrameworkCore.Metadata;
 using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage;
+using Microsoft.EntityFrameworkCore.Storage.Internal;
 using OperationsExample.Data;
+using System;
 
 namespace OperationsExample.Migrations
 {
@@ -12,21 +15,46 @@ partial class AppDbContextModelSnapshot : ModelSnapshot
     {
         protected override void BuildModel(ModelBuilder modelBuilder)
         {
+#pragma warning disable 612, 618
             modelBuilder
                 .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "1.1.2");
+                .HasAnnotation("ProductVersion", "2.0.1-rtm-125");
 
             modelBuilder.Entity("OperationsExample.Models.Article", b =>
                 {
                     b.Property<int>("Id")
                         .ValueGeneratedOnAdd();
 
+                    b.Property<int?>("AuthorId");
+
                     b.Property<string>("Name");
 
                     b.HasKey("Id");
 
+                    b.HasIndex("AuthorId");
+
                     b.ToTable("Articles");
                 });
+
+            modelBuilder.Entity("OperationsExample.Models.Author", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Authors");
+                });
+
+            modelBuilder.Entity("OperationsExample.Models.Article", b =>
+                {
+                    b.HasOne("OperationsExample.Models.Author", "Author")
+                        .WithMany("Articles")
+                        .HasForeignKey("AuthorId");
+                });
+#pragma warning restore 612, 618
         }
     }
 }
diff --git a/src/Examples/OperationsExample/Models/Article.cs b/src/Examples/OperationsExample/Models/Article.cs
index fc4b5d6647..4353c02ee2 100644
--- a/src/Examples/OperationsExample/Models/Article.cs
+++ b/src/Examples/OperationsExample/Models/Article.cs
@@ -1,10 +1,14 @@
-using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Models;
 
 namespace OperationsExample.Models
 {
     public class Article : Identifiable
     {
         [Attr("name")]
-        public string Name { get; set; }
+        public string Name { get; set; }
+
+        [HasOne("author")]
+        public Author Author { get; set; }
+        public int AuthorId { get; set; }
     }
 }
diff --git a/src/Examples/OperationsExample/Models/Author.cs b/src/Examples/OperationsExample/Models/Author.cs
new file mode 100644
index 0000000000..7d6039480a
--- /dev/null
+++ b/src/Examples/OperationsExample/Models/Author.cs
@@ -0,0 +1,14 @@
+using JsonApiDotNetCore.Models;
+using System.Collections.Generic;
+
+namespace OperationsExample.Models
+{
+    public class Author : Identifiable
+    {
+        [Attr("name")]
+        public string Name { get; set; }
+
+        [HasMany("articles")]
+        public List<Article> Articles { get; set; }
+    }
+}
diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj
index 48c2654722..ebbdc91fc1 100644
--- a/src/Examples/OperationsExample/OperationsExample.csproj
+++ b/src/Examples/OperationsExample/OperationsExample.csproj
@@ -11,6 +11,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="$(MicrosoftConfigurationVersion)" />
     <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="$(MicrosoftConfigurationVersion)" />
diff --git a/src/Examples/OperationsExample/Program.cs b/src/Examples/OperationsExample/Program.cs
index b528f47d15..1c2b6b267a 100644
--- a/src/Examples/OperationsExample/Program.cs
+++ b/src/Examples/OperationsExample/Program.cs
@@ -1,26 +1,15 @@
-using System.IO;
+using Microsoft.AspNetCore;
 using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
 
 namespace OperationsExample
 {
     public class Program
-    {
-        public static void Main(string[] args)
-        {
-            var config = new ConfigurationBuilder()
-                .AddCommandLine(args)
-                .AddEnvironmentVariables(prefix: "ASPNETCORE_")
-                .Build();
+    {
+        public static void Main(string[] args) => BuildWebHost(args).Run();
 
-            var host = new WebHostBuilder()
-                .UseConfiguration(config)
-                .UseKestrel()
-                .UseContentRoot(Directory.GetCurrentDirectory())
+        public static IWebHost BuildWebHost(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
                 .UseStartup<Startup>()
                 .Build();
-
-            host.Run();
-        }
     }
 }
diff --git a/src/Examples/OperationsExample/appsettings.json b/src/Examples/OperationsExample/appsettings.json
index c1061281cc..2bcbebd13a 100644
--- a/src/Examples/OperationsExample/appsettings.json
+++ b/src/Examples/OperationsExample/appsettings.json
@@ -1,13 +1,13 @@
-{
-  "Data": {
-    "DefaultConnection": "Host=localhost;Port=5432;Database=OperationsExample;User ID=postgres;Password=password"
-  },
-  "Logging": {
-    "IncludeScopes": false,
-    "LogLevel": {
-      "Default": "Trace",
-      "System": "Trace",
-      "Microsoft": "Trace"
+{
+    "Data": {
+        "DefaultConnection": "Host=localhost;Port=5432;Database=OperationsExample;User ID=postgres;Password=postgres"
+    },
+    "Logging": {
+        "IncludeScopes": false,
+        "LogLevel": {
+            "Default": "Trace",
+            "System": "Trace",
+            "Microsoft": "Trace"
+        }
     }
-  }
 }
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
index fafc70f161..6fff3a22c8 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
@@ -19,7 +19,8 @@ protected IActionResult Forbidden()
 
         protected IActionResult Error(Error error)
         {
-            var errorCollection = new ErrorCollection {
+            var errorCollection = new ErrorCollection
+            {
                 Errors = new List<Error> { error }
             };
             var result = new ObjectResult(errorCollection);
@@ -36,16 +37,16 @@ protected IActionResult Errors(ErrorCollection errors)
             return result;
         }
 
-        private int GetErrorStatusCode(ErrorCollection errors) 
+        private int GetErrorStatusCode(ErrorCollection errors)
         {
             var statusCodes = errors.Errors
                 .Select(e => e.StatusCode)
                 .Distinct()
                 .ToList();
 
-            if(statusCodes.Count == 1)
+            if (statusCodes.Count == 1)
                 return statusCodes[0];
-            
+
             return int.Parse(statusCodes.Max().ToString()[0] + "00");
         }
     }
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
index f3d0b6651d..69f4be8a89 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
@@ -18,6 +18,8 @@ public JsonApiOperationsController(
         [HttpPatch]
         public async Task<IActionResult> PatchAsync([FromBody] OperationsDocument doc)
         {
+            if (doc == null) return new StatusCodeResult(422);
+
             var results = await _operationsProcessor.ProcessAsync(doc.Operations);
 
             return Ok(new OperationsDocument(results));
diff --git a/src/JsonApiDotNetCore/Data/DbContextResolver.cs b/src/JsonApiDotNetCore/Data/DbContextResolver.cs
index 7cfe0a4278..e681e660bb 100644
--- a/src/JsonApiDotNetCore/Data/DbContextResolver.cs
+++ b/src/JsonApiDotNetCore/Data/DbContextResolver.cs
@@ -3,7 +3,7 @@
 
 namespace JsonApiDotNetCore.Data
 {
-    public class DbContextResolver<TContext>  : IDbContextResolver
+    public class DbContextResolver<TContext> : IDbContextResolver
         where TContext : DbContext
     {
         private readonly TContext _context;
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 9b33163810..604d65536b 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -148,12 +148,12 @@ private static void AddOperationServices(IServiceCollection services)
             services.AddScoped(typeof(IGetOpProcessor<>), typeof(GetOpProcessor<>));
             services.AddScoped(typeof(IGetOpProcessor<,>), typeof(GetOpProcessor<,>));
 
-            services.AddScoped(typeof(IReplaceOpProcessor<>), typeof(ReplaceOpProcessor<>));
-            services.AddScoped(typeof(IReplaceOpProcessor<,>), typeof(ReplaceOpProcessor<,>));
-
             services.AddScoped(typeof(IRemoveOpProcessor<>), typeof(RemoveOpProcessor<>));
             services.AddScoped(typeof(IRemoveOpProcessor<,>), typeof(RemoveOpProcessor<,>));
 
+            services.AddScoped(typeof(IUpdateOpProcessor<>), typeof(UpdateOpProcessor<>));
+            services.AddScoped(typeof(IUpdateOpProcessor<,>), typeof(UpdateOpProcessor<,>));
+
             services.AddSingleton<IOperationProcessorResolver, OperationProcessorResolver>();
             services.AddSingleton<IGenericProcessorFactory, GenericProcessorFactory>();
         }
diff --git a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs b/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
index 70aa070fc6..9871258b54 100644
--- a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
@@ -6,8 +6,8 @@ namespace JsonApiDotNetCore.Extensions
 {
     public static class JObjectExtensions
     {
-        public static bool TryParse<TPointer, TPointerBase>(this JObject obj, JSchema schema, out Pointer<TPointerBase> pointer)
-        where TPointer : Pointer<TPointerBase>, new()
+        internal static bool TryParse<TPointer, TPointerBase>(this JObject obj, JSchema schema, out Pointer<TPointerBase> pointer)
+            where TPointer : Pointer<TPointerBase>, new()
         {
             if (obj.IsValid(schema))
             {
@@ -19,4 +19,4 @@ public static bool TryParse<TPointer, TPointerBase>(this JObject obj, JSchema sc
             return false;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs b/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs
index ffe3310985..6b6905cd59 100644
--- a/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs
+++ b/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs
@@ -1,10 +1,14 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
 namespace JsonApiDotNetCore.Models.Operations
 {
+    [JsonConverter(typeof(StringEnumConverter))]
     public enum OperationCode
     {
         get = 1,
         add = 2,
-        replace = 3,
+        update = 3,
         remove = 4
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
index 0df8f64e72..53cdcfec06 100644
--- a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
+++ b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
@@ -5,12 +5,12 @@
 
 namespace JsonApiDotNetCore.Models.Pointers
 {
-    public class OperationsPointer : Pointer<Operation>
+    internal class OperationsPointer : Pointer<Operation>
     {
-        /// <exception cref="System.ArgumentNullException"></exception>
-        /// <exception cref="System.ArgumentException"></exception>
-        /// <exception cref="System.InvalidOperationException"></exception>
-        /// <exception cref="JsonApiDotNetCore.Internal.JsonApiException"></exception>
+        /// <exception cref="ArgumentNullException"></exception>
+        /// <exception cref="ArgumentException"></exception>
+        /// <exception cref="InvalidOperationException"></exception>
+        /// <exception cref="JsonApiException"></exception>
         public override object GetValue(object root)
         {
             if (root == null) throw new ArgumentNullException(nameof(root));
diff --git a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs b/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
index 27f0083904..d5e3a7924b 100644
--- a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
+++ b/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
@@ -3,7 +3,7 @@
 
 namespace JsonApiDotNetCore.Models.Pointers
 {
-    public abstract class Pointer<TPointerBase>
+    internal abstract class Pointer<TPointerBase>
     {
         public static JSchema JsonSchema { get; } = JSchema.Parse("{ 'pointer': {'type': 'string'} }");
 
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 6213edfd63..649d6435ff 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -31,8 +31,10 @@ public object Deserialize(string requestBody)
             {
                 var bodyJToken = JToken.Parse(requestBody);
 
-                if(RequestIsOperation(bodyJToken))
+                if (RequestIsOperation(bodyJToken))
                 {
+                    _jsonApiContext.IsBulkOperationRequest = true;
+
                     // TODO: determine whether or not the token should be re-used rather than performing full
                     // deserialization again from the string
                     var operations = JsonConvert.DeserializeObject<OperationsDocument>(requestBody);
@@ -54,8 +56,8 @@ public object Deserialize(string requestBody)
             }
         }
 
-        private bool RequestIsOperation(JToken bodyJToken) 
-            => _jsonApiContext.Options.EnableOperations 
+        private bool RequestIsOperation(JToken bodyJToken)
+            => _jsonApiContext.Options.EnableOperations
                 && (bodyJToken.SelectToken("operations") != null);
 
         public TEntity Deserialize<TEntity>(string requestBody) => (TEntity)Deserialize(requestBody);
@@ -82,7 +84,7 @@ public List<TEntity> DeserializeList<TEntity>(string requestBody)
             try
             {
                 var documents = JsonConvert.DeserializeObject<Documents>(requestBody);
-                
+
                 var deserializedList = new List<TEntity>();
                 foreach (var data in documents.Data)
                 {
@@ -196,7 +198,7 @@ private object SetHasOneRelationship(object entity,
                 if (relationshipAttr == null)
                     throw new JsonApiException(400, $"{_jsonApiContext.RequestEntity.EntityName} does not contain a relationship '{relationshipName}'");
 
-                var rio = (ResourceIdentifierObject) relationshipData.ExposedData;
+                var rio = (ResourceIdentifierObject)relationshipData.ExposedData;
 
                 if (rio == null) return entity;
 
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
index 8e94835266..20d119ff07 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
@@ -37,9 +37,12 @@ public string Serialize(object entity)
             if (entity == null)
                 return GetNullDataResponse();
 
-            if (entity.GetType() == typeof(ErrorCollection) || _jsonApiContext.RequestEntity == null)
+            if (entity.GetType() == typeof(ErrorCollection) || (_jsonApiContext.RequestEntity == null && _jsonApiContext.IsBulkOperationRequest == false))
                 return GetErrorJson(entity, _logger);
 
+            if (_jsonApiContext.IsBulkOperationRequest)
+                return _serialize(entity);
+
             if (entity is IEnumerable<IIdentifiable>)
                 return SerializeDocuments(entity);
 
@@ -86,4 +89,4 @@ private string _serialize(object obj)
             return JsonConvert.SerializeObject(obj, _jsonApiContext.Options.SerializerSettings);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index c16da81cfa..a73f0eb53a 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -27,6 +27,7 @@ public interface IJsonApiContext
         Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
         Type ControllerType { get; set; }
         Dictionary<string, object> DocumentMeta { get; set; }
+        bool IsBulkOperationRequest { get; set; }
 
         TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
     }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 66dfb46f8e..1ebf5aeea1 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -51,6 +51,7 @@ public JsonApiContext(
         public Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; } = new Dictionary<RelationshipAttribute, object>();
         public Type ControllerType { get; set; }
         public Dictionary<string, object> DocumentMeta { get; set; }
+        public bool IsBulkOperationRequest { get; set; }
 
         public IJsonApiContext ApplyContext<T>(object controller)
         {
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
index eeadc38e22..13714edbf3 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -9,8 +9,8 @@ public interface IOperationProcessorResolver
     {
         IOpProcessor LocateCreateService(Operation operation);
         IOpProcessor LocateGetService(Operation operation);
-        IOpProcessor LocateReplaceService(Operation operation);
         IOpProcessor LocateRemoveService(Operation operation);
+        IOpProcessor LocateUpdateService(Operation operation);
     }
 
     public class OperationProcessorResolver : IOperationProcessorResolver
@@ -22,8 +22,8 @@ public class OperationProcessorResolver : IOperationProcessorResolver
         // to reduce the cost of subsequent requests. in the future, this may be moved into setup code run at startup
         private ConcurrentDictionary<string, IOpProcessor> _createOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
         private ConcurrentDictionary<string, IOpProcessor> _getOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
-        private ConcurrentDictionary<string, IOpProcessor> _replaceOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
         private ConcurrentDictionary<string, IOpProcessor> _removeOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
+        private ConcurrentDictionary<string, IOpProcessor> _updateOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
 
         public OperationProcessorResolver(
             IGenericProcessorFactory processorFactory,
@@ -69,36 +69,36 @@ public IOpProcessor LocateGetService(Operation operation)
             return processor;
         }
 
-        public IOpProcessor LocateReplaceService(Operation operation)
+        public IOpProcessor LocateRemoveService(Operation operation)
         {
             var resource = operation.GetResourceTypeName();
 
-            if (_replaceOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
+            if (_removeOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
                 return cachedProcessor;
 
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
             var processor = _processorFactory.GetProcessor<IOpProcessor>(
-                typeof(IReplaceOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
+                typeof(IRemoveOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
             );
 
-            _replaceOpProcessors[resource] = processor;
+            _removeOpProcessors[resource] = processor;
 
             return processor;
         }
 
-        public IOpProcessor LocateRemoveService(Operation operation)
+        public IOpProcessor LocateUpdateService(Operation operation)
         {
             var resource = operation.GetResourceTypeName();
 
-            if (_removeOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
+            if (_updateOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
                 return cachedProcessor;
 
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
             var processor = _processorFactory.GetProcessor<IOpProcessor>(
-                typeof(IRemoveOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
+                typeof(IUpdateOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
             );
 
-            _removeOpProcessors[resource] = processor;
+            _updateOpProcessors[resource] = processor;
 
             return processor;
         }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index b687f1498f..7cb9765606 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -6,7 +6,6 @@
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Models.Operations;
-using JsonApiDotNetCore.Models.Pointers;
 using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Services.Operations
@@ -33,6 +32,7 @@ public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
         {
             var outputOps = new List<Operation>();
             var opIndex = 0;
+            OperationCode? lastAttemptedOperation = null; // used for error messages only
 
             using (var transaction = await _dbContext.Database.BeginTransactionAsync())
             {
@@ -40,30 +40,29 @@ public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
                 {
                     foreach (var op in inputOps)
                     {
+                        lastAttemptedOperation = op.Op;
                         await ProcessOperation(op, outputOps);
                         opIndex++;
                     }
 
                     transaction.Commit();
+                    return outputOps;
                 }
                 catch (JsonApiException e)
                 {
-                    outputOps = new List<Operation>();
-                    throw new JsonApiException(e.GetStatusCode(), $"Transaction failed on operation[{opIndex}].", e);
+                    transaction.Rollback();
+                    throw new JsonApiException(e.GetStatusCode(), $"Transaction failed on operation[{opIndex}] ({lastAttemptedOperation}).", e);
                 }
                 catch (Exception e)
                 {
-                    throw new JsonApiException(500, $"Transaction failed on operation[{opIndex}] for an unexpected reason.", e);
+                    transaction.Rollback();
+                    throw new JsonApiException(500, $"Transaction failed on operation[{opIndex}] ({lastAttemptedOperation}) for an unexpected reason.", e);
                 }
             }
-
-            return outputOps;
         }
 
         private async Task ProcessOperation(Operation op, List<Operation> outputOps)
         {
-            var operationsPointer = new OperationsPointer();
-
             ReplaceLocalIdsInResourceObject(op.DataObject, outputOps);
             ReplaceLocalIdsInRef(op.Ref, outputOps);
 
@@ -88,39 +87,39 @@ private void ReplaceLocalIdsInResourceObject(ResourceObject resourceObject, List
             // if(HasLocalId(resourceObject))
             //     resourceObject.Id = GetIdFromLocalId(outputOps, resourceObject.LocalId);
 
-            if (resourceObject.Relationships != null) 
-            { 
-                foreach (var relationshipDictionary in resourceObject.Relationships) 
-                { 
-                    if (relationshipDictionary.Value.IsHasMany) 
-                    { 
-                        foreach (var relationship in relationshipDictionary.Value.ManyData) 
-                            if(HasLocalId(relationship))
+            if (resourceObject.Relationships != null)
+            {
+                foreach (var relationshipDictionary in resourceObject.Relationships)
+                {
+                    if (relationshipDictionary.Value.IsHasMany)
+                    {
+                        foreach (var relationship in relationshipDictionary.Value.ManyData)
+                            if (HasLocalId(relationship))
                                 relationship.Id = GetIdFromLocalId(outputOps, relationship.LocalId);
-                    } 
+                    }
                     else
                     {
                         var relationship = relationshipDictionary.Value.SingleData;
-                        if(HasLocalId(relationship))
+                        if (HasLocalId(relationship))
                             relationship.Id = GetIdFromLocalId(outputOps, relationship.LocalId);
                     }
-                } 
+                }
             }
         }
 
-        private void ReplaceLocalIdsInRef(ResourceReference resourceRef, List<Operation> outputOps) 
-        { 
+        private void ReplaceLocalIdsInRef(ResourceReference resourceRef, List<Operation> outputOps)
+        {
             if (resourceRef == null) return;
-            if(HasLocalId(resourceRef))
+            if (HasLocalId(resourceRef))
                 resourceRef.Id = GetIdFromLocalId(outputOps, resourceRef.LocalId);
         }
 
         private bool HasLocalId(ResourceIdentifierObject rio) => string.IsNullOrEmpty(rio.LocalId) == false;
 
-        private string GetIdFromLocalId(List<Operation> outputOps, string localId)  
+        private string GetIdFromLocalId(List<Operation> outputOps, string localId)
         {
             var referencedOp = outputOps.FirstOrDefault(o => o.DataObject.LocalId == localId);
-            if(referencedOp == null) throw new JsonApiException(400, $"Could not locate lid '{localId}' in document.");
+            if (referencedOp == null) throw new JsonApiException(400, $"Could not locate lid '{localId}' in document.");
             return referencedOp.DataObject.Id;
         }
 
@@ -132,10 +131,10 @@ private IOpProcessor GetOperationsProcessor(Operation op)
                     return _processorResolver.LocateCreateService(op);
                 case OperationCode.get:
                     return _processorResolver.LocateGetService(op);
-                case OperationCode.replace:
-                    return _processorResolver.LocateReplaceService(op);
                 case OperationCode.remove:
                     return _processorResolver.LocateRemoveService(op);
+                case OperationCode.update:
+                    return _processorResolver.LocateUpdateService(op);
                 default:
                     throw new JsonApiException(400, $"'{op.Op}' is not a valid operation code");
             }
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
index 251b81a5d6..4f50bbf4da 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
@@ -61,6 +61,10 @@ public async Task<Operation> ProcessAsync(Operation operation)
                 _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
                 result);
 
+            // we need to persist the original request localId so that subsequent operations
+            // can locate the result of this operation by its localId
+            operationResult.DataObject.LocalId = operation.DataObject.LocalId;
+
             return operationResult;
         }
     }
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
index c96af5bb37..236a76d084 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
@@ -1,4 +1,3 @@
-using System;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Internal;
@@ -52,14 +51,12 @@ public async Task<Operation> ProcessAsync(Operation operation)
         {
             var stringId = operation.Ref?.Id?.ToString();
             if (string.IsNullOrWhiteSpace(stringId))
-                throw new JsonApiException(400, "The data.id parameter is required for delete operations");
+                throw new JsonApiException(400, "The ref.id parameter is required for remove operations");
 
             var id = TypeHelper.ConvertType<TId>(stringId);
             var result = await _service.DeleteAsync(id);
 
-            var operationResult = new Operation { };
-
-            return operationResult;
+            return null;
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
similarity index 79%
rename from src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs
rename to src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
index 27cf348397..b626fbe746 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
@@ -7,18 +7,18 @@
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
-    public interface IReplaceOpProcessor<T> : IOpProcessor
+    public interface IUpdateOpProcessor<T> : IOpProcessor
         where T : class, IIdentifiable<int>
     { }
 
-    public interface IReplaceOpProcessor<T, TId> : IOpProcessor
+    public interface IUpdateOpProcessor<T, TId> : IOpProcessor
         where T : class, IIdentifiable<TId>
     { }
 
-    public class ReplaceOpProcessor<T> : ReplaceOpProcessor<T, int>
+    public class UpdateOpProcessor<T> : UpdateOpProcessor<T, int>
         where T : class, IIdentifiable<int>
     {
-        public ReplaceOpProcessor(
+        public UpdateOpProcessor(
             IUpdateService<T, int> service,
             IJsonApiDeSerializer deSerializer,
             IDocumentBuilder documentBuilder,
@@ -27,7 +27,7 @@ IContextGraph contextGraph
         { }
     }
 
-    public class ReplaceOpProcessor<T, TId> : IReplaceOpProcessor<T, TId>
+    public class UpdateOpProcessor<T, TId> : ICreateOpProcessor<T, TId>
          where T : class, IIdentifiable<TId>
     {
         private readonly IUpdateService<T, TId> _service;
@@ -35,7 +35,7 @@ public class ReplaceOpProcessor<T, TId> : IReplaceOpProcessor<T, TId>
         private readonly IDocumentBuilder _documentBuilder;
         private readonly IContextGraph _contextGraph;
 
-        public ReplaceOpProcessor(
+        public UpdateOpProcessor(
             IUpdateService<T, TId> service,
             IJsonApiDeSerializer deSerializer,
             IDocumentBuilder documentBuilder,
@@ -49,17 +49,15 @@ public ReplaceOpProcessor(
 
         public async Task<Operation> ProcessAsync(Operation operation)
         {
-            var model = (T)_deSerializer.DocumentToObject(operation.DataObject);
-
             if (string.IsNullOrWhiteSpace(operation?.DataObject?.Id?.ToString()))
                 throw new JsonApiException(400, "The data.id parameter is required for replace operations");
 
-            var id = TypeHelper.ConvertType<TId>(operation.DataObject.Id);
-            var result = await _service.UpdateAsync(id, model);
+            var model = (T)_deSerializer.DocumentToObject(operation.DataObject);
+            var result = await _service.UpdateAsync(model.Id, model);
 
             var operationResult = new Operation
             {
-                Op = OperationCode.replace
+                Op = OperationCode.update
             };
 
             operationResult.Data = _documentBuilder.GetData(
diff --git a/src/JsonApiDotNetCore/api/.manifest b/src/JsonApiDotNetCore/api/.manifest
index c5b25fa365..a8237f4ff1 100644
--- a/src/JsonApiDotNetCore/api/.manifest
+++ b/src/JsonApiDotNetCore/api/.manifest
@@ -218,7 +218,6 @@
   "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApiInternals``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
   "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.SerializeAsJsonApi(Microsoft.AspNetCore.Mvc.MvcOptions,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
   "JsonApiDotNetCore.Extensions.JObjectExtensions": "JsonApiDotNetCore.Extensions.JObjectExtensions.yml",
-  "JsonApiDotNetCore.Extensions.JObjectExtensions.TryParse``2(Newtonsoft.Json.Linq.JObject,Newtonsoft.Json.Schema.JSchema,JsonApiDotNetCore.Models.Pointers.Pointer{``1}@)": "JsonApiDotNetCore.Extensions.JObjectExtensions.yml",
   "JsonApiDotNetCore.Extensions.StringExtensions": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
   "JsonApiDotNetCore.Extensions.StringExtensions.Dasherize(System.String)": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
   "JsonApiDotNetCore.Extensions.StringExtensions.ToProperCase(System.String)": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
@@ -443,7 +442,7 @@
   "JsonApiDotNetCore.Models.Operations.OperationCode.add": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
   "JsonApiDotNetCore.Models.Operations.OperationCode.get": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
   "JsonApiDotNetCore.Models.Operations.OperationCode.remove": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
-  "JsonApiDotNetCore.Models.Operations.OperationCode.replace": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
+  "JsonApiDotNetCore.Models.Operations.OperationCode.update": "JsonApiDotNetCore.Models.Operations.OperationCode.yml",
   "JsonApiDotNetCore.Models.Operations.OperationsDocument": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml",
   "JsonApiDotNetCore.Models.Operations.OperationsDocument.#ctor": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml",
   "JsonApiDotNetCore.Models.Operations.OperationsDocument.#ctor(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml",
@@ -456,13 +455,6 @@
   "JsonApiDotNetCore.Models.Operations.Params.Sort": "JsonApiDotNetCore.Models.Operations.Params.yml",
   "JsonApiDotNetCore.Models.Operations.ResourceReference": "JsonApiDotNetCore.Models.Operations.ResourceReference.yml",
   "JsonApiDotNetCore.Models.Operations.ResourceReference.Relationship": "JsonApiDotNetCore.Models.Operations.ResourceReference.yml",
-  "JsonApiDotNetCore.Models.Pointers": "JsonApiDotNetCore.Models.Pointers.yml",
-  "JsonApiDotNetCore.Models.Pointers.OperationsPointer": "JsonApiDotNetCore.Models.Pointers.OperationsPointer.yml",
-  "JsonApiDotNetCore.Models.Pointers.OperationsPointer.GetValue(System.Object)": "JsonApiDotNetCore.Models.Pointers.OperationsPointer.yml",
-  "JsonApiDotNetCore.Models.Pointers.Pointer`1": "JsonApiDotNetCore.Models.Pointers.Pointer-1.yml",
-  "JsonApiDotNetCore.Models.Pointers.Pointer`1.GetValue(System.Object)": "JsonApiDotNetCore.Models.Pointers.Pointer-1.yml",
-  "JsonApiDotNetCore.Models.Pointers.Pointer`1.JsonSchema": "JsonApiDotNetCore.Models.Pointers.Pointer-1.yml",
-  "JsonApiDotNetCore.Models.Pointers.Pointer`1.PointerAddress": "JsonApiDotNetCore.Models.Pointers.Pointer-1.yml",
   "JsonApiDotNetCore.Models.RelationshipAttribute": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
   "JsonApiDotNetCore.Models.RelationshipAttribute.#ctor(System.String,JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
   "JsonApiDotNetCore.Models.RelationshipAttribute.DocumentLinks": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
@@ -572,6 +564,7 @@
   "JsonApiDotNetCore.Services.IJsonApiContext.GenericProcessorFactory": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
   "JsonApiDotNetCore.Services.IJsonApiContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
   "JsonApiDotNetCore.Services.IJsonApiContext.IncludedRelationships": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
+  "JsonApiDotNetCore.Services.IJsonApiContext.IsBulkOperationRequest": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
   "JsonApiDotNetCore.Services.IJsonApiContext.IsRelationshipData": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
   "JsonApiDotNetCore.Services.IJsonApiContext.IsRelationshipPath": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
   "JsonApiDotNetCore.Services.IJsonApiContext.MetaBuilder": "JsonApiDotNetCore.Services.IJsonApiContext.yml",
@@ -610,6 +603,7 @@
   "JsonApiDotNetCore.Services.JsonApiContext.GenericProcessorFactory": "JsonApiDotNetCore.Services.JsonApiContext.yml",
   "JsonApiDotNetCore.Services.JsonApiContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.JsonApiContext.yml",
   "JsonApiDotNetCore.Services.JsonApiContext.IncludedRelationships": "JsonApiDotNetCore.Services.JsonApiContext.yml",
+  "JsonApiDotNetCore.Services.JsonApiContext.IsBulkOperationRequest": "JsonApiDotNetCore.Services.JsonApiContext.yml",
   "JsonApiDotNetCore.Services.JsonApiContext.IsRelationshipData": "JsonApiDotNetCore.Services.JsonApiContext.yml",
   "JsonApiDotNetCore.Services.JsonApiContext.IsRelationshipPath": "JsonApiDotNetCore.Services.JsonApiContext.yml",
   "JsonApiDotNetCore.Services.JsonApiContext.MetaBuilder": "JsonApiDotNetCore.Services.JsonApiContext.yml",
@@ -623,7 +617,7 @@
   "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateCreateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
   "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateGetService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
   "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateRemoveService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
-  "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateReplaceService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateUpdateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml",
   "JsonApiDotNetCore.Services.Operations.IOperationsProcessor": "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.yml",
   "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.ProcessAsync(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.yml",
   "JsonApiDotNetCore.Services.Operations.IOpProcessor": "JsonApiDotNetCore.Services.Operations.IOpProcessor.yml",
@@ -633,7 +627,7 @@
   "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateCreateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
   "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateGetService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
   "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateRemoveService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
-  "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateReplaceService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
+  "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateUpdateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml",
   "JsonApiDotNetCore.Services.Operations.OperationsProcessor": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml",
   "JsonApiDotNetCore.Services.Operations.OperationsProcessor.#ctor(JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver,JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml",
   "JsonApiDotNetCore.Services.Operations.OperationsProcessor.ProcessAsync(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml",
@@ -654,18 +648,18 @@
   "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor-1.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor-2.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.IReplaceOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IReplaceOpProcessor-1.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.IReplaceOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IReplaceOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.IUpdateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IUpdateOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.IUpdateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IUpdateOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-1.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IDeleteService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-1.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IDeleteService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-1.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IUpdateService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-1.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-2.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IUpdateService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-2.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.ReplaceOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IUpdateService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IUpdateService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.QueryAccessor": "JsonApiDotNetCore.Services.QueryAccessor.yml",
   "JsonApiDotNetCore.Services.QueryAccessor.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,Microsoft.Extensions.Logging.ILogger{JsonApiDotNetCore.Services.QueryAccessor})": "JsonApiDotNetCore.Services.QueryAccessor.yml",
   "JsonApiDotNetCore.Services.QueryAccessor.GetRequired``1(System.String)": "JsonApiDotNetCore.Services.QueryAccessor.yml",
diff --git a/test/OperationsExampleTests/Replace/ReplaceTests.cs b/test/OperationsExampleTests/Update/UpdateTests.cs
similarity index 93%
rename from test/OperationsExampleTests/Replace/ReplaceTests.cs
rename to test/OperationsExampleTests/Update/UpdateTests.cs
index 521dcd979b..de05881963 100644
--- a/test/OperationsExampleTests/Replace/ReplaceTests.cs
+++ b/test/OperationsExampleTests/Update/UpdateTests.cs
@@ -1,112 +1,112 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Threading.Tasks;
-using Bogus;
-using JsonApiDotNetCore.Models.Operations;
-using OperationsExample.Data;
-using OperationsExampleTests.Factories;
-using Xunit;
-
-namespace OperationsExampleTests
-{
-    [Collection("WebHostCollection")]
-    public class ReplaceTests
-    {
-        private readonly Fixture _fixture;
-        private readonly Faker _faker = new Faker();
-
-        public ReplaceTests(Fixture fixture)
-        {
-            _fixture = fixture;
-        }
-
-        [Fact]
-        public async Task Can_Update_Article()
-        {
-            // arrange
-            var context = _fixture.GetService<AppDbContext>();
-            var article = ArticleFactory.Get();
-            var updates = ArticleFactory.Get();
-            context.Articles.Add(article);
-            context.SaveChanges();
-
-            var content = new
-            {
-                operations = new[] {
-                    new {
-                        op = "replace",
-                        data = new {
-                            type = "articles",
-                            id = article.Id,
-                            attributes = new {
-                                name = updates.Name
-                            }
-                        }
-                    },
-                }
-            };
-
-            // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
-
-            // assert
-            Assert.NotNull(result.response);
-            Assert.NotNull(result.data);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(1, result.data.Operations.Count);
-
-            var attrs = result.data.Operations.Single().DataObject.Attributes;
-            Assert.Equal(updates.Name, attrs["name"]);
-        }
-
-        [Fact]
-        public async Task Can_Update_Articles()
-        {
-            // arrange
-            var count = _faker.Random.Int(1, 10);
-            var context = _fixture.GetService<AppDbContext>();
-
-            var articles = ArticleFactory.Get(count);
-            var updates = ArticleFactory.Get(count);
-
-            context.Articles.AddRange(articles);
-            context.SaveChanges();
-
-            var content = new
-            {
-                operations = new List<object>()
-            };
-
-            for (int i = 0; i < count; i++)
-                content.operations.Add(new
-                {
-                    op = "replace",
-                    data = new
-                    {
-                        type = "articles",
-                        id = articles[i].Id,
-                        attributes = new
-                        {
-                            name = updates[i].Name
-                        }
-                    }
-                });
-
-            // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
-
-            // assert
-            Assert.NotNull(result.response);
-            Assert.NotNull(result.data);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(count, result.data.Operations.Count);
-
-            for (int i = 0; i < count; i++)
-            {
-                var attrs = result.data.Operations[i].DataObject.Attributes;
-                Assert.Equal(updates[i].Name, attrs["name"]);
-            }
-        }
-    }
-}
+using Bogus;
+using JsonApiDotNetCore.Models.Operations;
+using OperationsExample.Data;
+using OperationsExampleTests.Factories;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace OperationsExampleTests.Update
+{
+    [Collection("WebHostCollection")]
+    public class UpdateTests
+    {
+        private readonly Fixture _fixture;
+        private readonly Faker _faker = new Faker();
+
+        public UpdateTests(Fixture fixture)
+        {
+            _fixture = fixture;
+        }
+
+        [Fact]
+        public async Task Can_Update_Article()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var article = ArticleFactory.Get();
+            var updates = ArticleFactory.Get();
+            context.Articles.Add(article);
+            context.SaveChanges();
+
+            var content = new
+            {
+                operations = new[] {
+                    new {
+                        op = "replace",
+                        data = new {
+                            type = "articles",
+                            id = article.Id,
+                            attributes = new {
+                                name = updates.Name
+                            }
+                        }
+                    },
+                }
+            };
+
+            // act
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(1, result.data.Operations.Count);
+
+            var attrs = result.data.Operations.Single().DataObject.Attributes;
+            Assert.Equal(updates.Name, attrs["name"]);
+        }
+
+        [Fact]
+        public async Task Can_Update_Articles()
+        {
+            // arrange
+            var count = _faker.Random.Int(1, 10);
+            var context = _fixture.GetService<AppDbContext>();
+
+            var articles = ArticleFactory.Get(count);
+            var updates = ArticleFactory.Get(count);
+
+            context.Articles.AddRange(articles);
+            context.SaveChanges();
+
+            var content = new
+            {
+                operations = new List<object>()
+            };
+
+            for (int i = 0; i < count; i++)
+                content.operations.Add(new
+                {
+                    op = "replace",
+                    data = new
+                    {
+                        type = "articles",
+                        id = articles[i].Id,
+                        attributes = new
+                        {
+                            name = updates[i].Name
+                        }
+                    }
+                });
+
+            // act
+            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(count, result.data.Operations.Count);
+
+            for (int i = 0; i < count; i++)
+            {
+                var attrs = result.data.Operations[i].DataObject.Attributes;
+                Assert.Equal(updates[i].Name, attrs["name"]);
+            }
+        }
+    }
+}
diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
index 0a7fd501ae..5b98927119 100644
--- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Data;
@@ -169,7 +169,7 @@ public async Task ProcessAsync_Performs_LocalId_ReplacementAsync_In_References()
             var updateOpProcessorMock = new Mock<IOpProcessor>();
             updateOpProcessorMock.Setup(m => m.ProcessAsync(It.Is<Operation>(op => op.DataObject.Type.ToString() == "authors")))
                 .ReturnsAsync((Operation)null);
-            _resolverMock.Setup(m => m.LocateReplaceService(It.IsAny<Operation>()))
+            _resolverMock.Setup(m => m.LocateUpdateService(It.IsAny<Operation>()))
                 .Returns(updateOpProcessorMock.Object);
 
             _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object);

From aea5385b277c71ec1680dc120fd6de189a855732 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 25 Mar 2018 14:16:57 -0500
Subject: [PATCH 102/227] add tests for bulk operations

---
 Build.ps1                                     |   5 +-
 JsonApiDotnetCore.sln                         |   4 +
 build.sh                                      |   3 +-
 .../JsonApiOperationsController.cs            |  38 ++++++-
 test/OperationsExampleTests/Add/AddTests.cs   | 106 ++++++++++++++----
 .../Factories/AuthorFactory.cs                |  25 +++++
 6 files changed, 156 insertions(+), 25 deletions(-)
 create mode 100644 test/OperationsExampleTests/Factories/AuthorFactory.cs

diff --git a/Build.ps1 b/Build.ps1
index e51473adf2..bfbd989415 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -32,6 +32,9 @@ CheckLastExitCode
 dotnet test ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
 CheckLastExitCode
 
+dotnet test ./test/OperationsExampleTests/OperationsExampleTests.csproj
+CheckLastExitCode
+
 dotnet build .\src\JsonApiDotNetCore -c Release
 CheckLastExitCode
 
@@ -57,4 +60,4 @@ Else {
     Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision"
     dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision 
     CheckLastExitCode
-}
\ No newline at end of file
+}
diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index ac45f83cdf..4b7cf5ea47 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -15,6 +15,10 @@ EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C5B4D998-CECB-454D-9F32-085A897577BE}"
 	ProjectSection(SolutionItems) = preProject
 		.gitignore = .gitignore
+		.travis.yml = .travis.yml
+		appveyor.yml = appveyor.yml
+		Build.ps1 = Build.ps1
+		build.sh = build.sh
 		Directory.Build.props = Directory.Build.props
 		README.md = README.md
 	EndProjectSection
diff --git a/build.sh b/build.sh
index 441470e65d..50f2ab9c99 100755
--- a/build.sh
+++ b/build.sh
@@ -7,4 +7,5 @@ dotnet restore
 
 dotnet test ./test/UnitTests/UnitTests.csproj
 dotnet test ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
-dotnet test ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
\ No newline at end of file
+dotnet test ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
+dotnet test ./test/OperationsExampleTests/OperationsExampleTests.csproj
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
index 69f4be8a89..c3b667bc7d 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
@@ -5,18 +5,50 @@
 
 namespace JsonApiDotNetCore.Controllers
 {
+    /// <summary>
+    /// A controller to be used for bulk operations as defined in the json:api 1.1 specification
+    /// </summary>
     public class JsonApiOperationsController : Controller
     {
         private readonly IOperationsProcessor _operationsProcessor;
 
-        public JsonApiOperationsController(
-            IOperationsProcessor operationsProcessor)
+        /// <param name="operationsProcessor">
+        /// The processor to handle bulk operations.
+        /// </param>
+        public JsonApiOperationsController(IOperationsProcessor operationsProcessor)
         {
             _operationsProcessor = operationsProcessor;
         }
 
+        /// <summary>
+        /// Bulk endpoint for json:api operations
+        /// </summary>
+        /// <param name="doc">
+        /// A json:api operations request document
+        /// </param>
+        /// <example>
+        /// <code>
+        /// PATCH /api/bulk HTTP/1.1
+        /// Content-Type: application/vnd.api+json
+        /// 
+        /// {
+        ///   "operations": [{
+        ///     "op": "add",
+        ///     "ref": {
+        ///       "type": "authors"
+        ///     },
+        ///     "data": {
+        ///       "type": "authors",
+        ///       "attributes": {
+        ///         "name": "jaredcnance"
+        ///       }
+        ///     }
+        ///   }]
+        /// }
+        /// </code>
+        /// </example>
         [HttpPatch]
-        public async Task<IActionResult> PatchAsync([FromBody] OperationsDocument doc)
+        public virtual async Task<IActionResult> PatchAsync([FromBody] OperationsDocument doc)
         {
             if (doc == null) return new StatusCodeResult(422);
 
diff --git a/test/OperationsExampleTests/Add/AddTests.cs b/test/OperationsExampleTests/Add/AddTests.cs
index 2d765e1633..656cb134b5 100644
--- a/test/OperationsExampleTests/Add/AddTests.cs
+++ b/test/OperationsExampleTests/Add/AddTests.cs
@@ -3,7 +3,6 @@
 using System.Net;
 using System.Threading.Tasks;
 using Bogus;
-using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Models.Operations;
 using Microsoft.EntityFrameworkCore;
 using OperationsExample.Data;
@@ -24,20 +23,20 @@ public AddTests(Fixture fixture)
         }
 
         [Fact]
-        public async Task Can_Create_Article()
+        public async Task Can_Create_Author()
         {
             // arrange
             var context = _fixture.GetService<AppDbContext>();
-            var article = ArticleFactory.Get();
+            var author = AuthorFactory.Get();
             var content = new
             {
                 operations = new[] {
                     new {
                         op = "add",
                         data = new {
-                            type = "articles",
+                            type = "authors",
                             attributes = new {
-                                name = article.Name
+                                name = author.Name
                             }
                         }
                     }
@@ -48,21 +47,21 @@ public async Task Can_Create_Article()
             var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(result);
+            Assert.NotNull(result.response);
             Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
 
-            var id = (string)result.data.Operations.Single().DataObject.Id;
-            var lastArticle = await context.Articles.SingleAsync(a => a.StringId == id);
-            Assert.Equal(article.Name, lastArticle.Name);
+            var id = result.data.Operations.Single().DataObject.Id;
+            var lastAuthor = await context.Authors.SingleAsync(a => a.StringId == id);
+            Assert.Equal(author.Name, lastAuthor.Name);
         }
 
         [Fact]
-        public async Task Can_Create_Articles()
+        public async Task Can_Create_Authors()
         {
             // arrange
             var expectedCount = _faker.Random.Int(1, 10);
             var context = _fixture.GetService<AppDbContext>();
-            var articles = ArticleFactory.Get(expectedCount);
+            var authors = AuthorFactory.Get(expectedCount);
             var content = new
             {
                 operations = new List<object>()
@@ -76,10 +75,10 @@ public async Task Can_Create_Articles()
                          op = "add",
                          data = new
                          {
-                             type = "articles",
+                             type = "authors",
                              attributes = new
                              {
-                                 name = articles[i].Name
+                                 name = authors[i].Name
                              }
                          }
                      }
@@ -87,19 +86,86 @@ public async Task Can_Create_Articles()
             }
 
             // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(result);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(expectedCount, result.data.Operations.Count);
+            Assert.NotNull(response);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Equal(expectedCount, data.Operations.Count);
 
             for (int i = 0; i < expectedCount; i++)
             {
-                var data = result.data.Operations[i].DataObject;
-                var article = context.Articles.Single(a => a.StringId == data.Id.ToString());
-                Assert.Equal(articles[i].Name, article.Name);
+                var dataObject = data.Operations[i].DataObject;
+                var author = context.Authors.Single(a => a.StringId == dataObject.ToString());
+                Assert.Equal(authors[i].Name, author.Name);
             }
+        }
+
+        [Fact]
+        public async Task Can_Create_Author_With_Article()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var author = AuthorFactory.Get();
+            var article = ArticleFactory.Get();
+            const string authorLocalId = "author-1";
+
+            var content = new
+            {
+                operations = new object[] {
+                    new {
+                        op = "add",
+                        data = new {
+                            lid = authorLocalId,
+                            type = "authors",
+                            attributes = new {
+                                name = author.Name
+                            },
+                        }
+                    },
+                    new {
+                        op = "add",
+                        data = new {
+                            type = "articles",
+                            attributes = new {
+                                name = article.Name
+                            },
+                            relationships = new {
+                                author = new {
+                                    data = new {
+                                        type = "authors",
+                                        lid = authorLocalId
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            };
+
+            // act
+            var (response, data) = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(response);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Equal(2, data.Operations.Count);
+
+            var authorOperationResult = data.Operations[0];
+            var id = authorOperationResult.DataObject.Id;
+            var lastAuthor = await context.Authors
+                .Include(a => a.Articles)
+                .SingleAsync(a => a.StringId == id);
+            var articleOperationResult = data.Operations[1];
+
+            // author validation
+            Assert.Equal(authorLocalId, authorOperationResult.DataObject.LocalId);
+            Assert.Equal(author.Name, lastAuthor.Name);
+
+            // article validation
+            Assert.Equal(1, lastAuthor.Articles.Count);
+            Assert.Equal(article.Name, lastAuthor.Articles[0].Name);
+            Assert.Equal(articleOperationResult.DataObject.Id, lastAuthor.Articles[0].StringId);
         }
     }
 }
diff --git a/test/OperationsExampleTests/Factories/AuthorFactory.cs b/test/OperationsExampleTests/Factories/AuthorFactory.cs
new file mode 100644
index 0000000000..2afe914b54
--- /dev/null
+++ b/test/OperationsExampleTests/Factories/AuthorFactory.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using Bogus;
+using OperationsExample.Models;
+
+namespace OperationsExampleTests.Factories
+{
+    public static class AuthorFactory
+    {
+        public static Author Get()
+        {
+            var faker = new Faker<Author>();
+            faker.RuleFor(m => m.Name, f => f.Person.UserName);
+            return faker.Generate();
+        }
+
+        public static List<Author> Get(int count)
+        {
+            var authors = new List<Author>();
+            for (int i = 0; i < count; i++)
+                authors.Add(Get());
+
+            return authors;
+        }
+    }
+}

From a86963672ce79b8466339d8b0ed51a9af2301752 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 25 Mar 2018 15:25:09 -0500
Subject: [PATCH 103/227] test transaction rollbacks

---
 src/Examples/OperationsExample/Startup.cs     |  3 +-
 .../Generics/GenericProcessorFactory.cs       |  5 +-
 src/JsonApiDotNetCore/api/.manifest           |  2 +-
 .../Transactions/TransactionFailureTests.cs   | 89 +++++++++++++++++++
 4 files changed, 94 insertions(+), 5 deletions(-)
 create mode 100644 test/OperationsExampleTests/Transactions/TransactionFailureTests.cs

diff --git a/src/Examples/OperationsExample/Startup.cs b/src/Examples/OperationsExample/Startup.cs
index 7e4444dfb5..6e13b2964d 100644
--- a/src/Examples/OperationsExample/Startup.cs
+++ b/src/Examples/OperationsExample/Startup.cs
@@ -1,6 +1,5 @@
-using System;
+using System;
 using JsonApiDotNetCore.Extensions;
-using JsonApiDotNetCore.Models;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.EntityFrameworkCore;
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
index 3f88010e0a..585cebd715 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
@@ -1,3 +1,4 @@
+using Microsoft.AspNetCore.Http;
 using System;
 
 namespace JsonApiDotNetCore.Internal.Generics
@@ -30,9 +31,9 @@ public class GenericProcessorFactory : IGenericProcessorFactory
     {
         private readonly IServiceProvider _serviceProvider;
 
-        public GenericProcessorFactory(IServiceProvider serviceProvider)
+        public GenericProcessorFactory(IHttpContextAccessor httpContextAccessor)
         {
-            _serviceProvider = serviceProvider;
+            _serviceProvider = httpContextAccessor.HttpContext.RequestServices;
         }
 
         public TInterface GetProcessor<TInterface>(Type openGenericType, Type resourceType)
diff --git a/src/JsonApiDotNetCore/api/.manifest b/src/JsonApiDotNetCore/api/.manifest
index a8237f4ff1..632c57f5eb 100644
--- a/src/JsonApiDotNetCore/api/.manifest
+++ b/src/JsonApiDotNetCore/api/.manifest
@@ -283,7 +283,7 @@
   "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.SetRelationships(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
-  "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.#ctor(System.IServiceProvider)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.#ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.GetProcessor``1(System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.GetProcessor``1(System.Type,System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
   "JsonApiDotNetCore.Internal.Generics.IGenericProcessor": "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.yml",
diff --git a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
new file mode 100644
index 0000000000..53b1e37b5a
--- /dev/null
+++ b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+using Bogus;
+using JsonApiDotNetCore.Internal;
+using Microsoft.EntityFrameworkCore;
+using OperationsExample.Data;
+using OperationsExampleTests.Factories;
+using Xunit;
+
+namespace OperationsExampleTests
+{
+    [Collection("WebHostCollection")]
+    public class TransactionFailureTests
+    {
+        private readonly Fixture _fixture;
+        private readonly Faker _faker = new Faker();
+
+        public TransactionFailureTests(Fixture fixture)
+        {
+            _fixture = fixture;
+        }
+
+        [Fact]
+        public async Task Cannot_Create_Author_If_Article_Creation_Fails()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var author = AuthorFactory.Get();
+            var article = ArticleFactory.Get();
+
+            // do this so that the name is random enough for db validations
+            author.Name = Guid.NewGuid().ToString("N");
+            article.Name = Guid.NewGuid().ToString("N");
+
+            var content = new
+            {
+                operations = new object[] {
+                    new {
+                        op = "add",
+                        data = new {
+                            type = "authors",
+                            attributes = new {
+                                name = author.Name
+                            },
+                        }
+                    },
+                    new {
+                        op = "add",
+                        data = new {
+                            type = "articles",
+                            attributes = new {
+                                name = article.Name
+                            },
+                            // by not including the author, the article creation will fail
+                            // relationships = new {
+                            //    author = new {
+                            //        data = new {
+                            //            type = "authors",
+                            //            lid = authorLocalId
+                            //        }
+                            //    }
+                            // }
+                        }
+                    }
+                }
+            };
+
+            // act
+            var (response, data) = await _fixture.PatchAsync<ErrorCollection>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(response);
+            // for now, it is up to application implementations to perform validation and 
+            // provide the proper HTTP response code
+            Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+            Assert.Equal(1, data.Errors.Count);
+            Assert.Contains("operation[1] (add)", data.Errors[0].Title);
+
+            var dbAuthors = await context.Authors.Where(a => a.Name == author.Name).ToListAsync();
+            var dbArticles = await context.Articles.Where(a => a.Name == article.Name).ToListAsync();
+            Assert.Empty(dbAuthors);
+            Assert.Empty(dbArticles);
+        }
+    }
+}

From a20bd53784a099a683da78d93f200128414c7cb9 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 25 Mar 2018 20:32:35 -0500
Subject: [PATCH 104/227] fix(transactions): locate services using request
 scoped service provider

---
 .../Internal/Generics/GenericProcessorFactory.cs              | 4 ++++
 test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs  | 3 ++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
index 585cebd715..27d15b163d 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
@@ -14,7 +14,9 @@ public interface IGenericProcessorFactory
         /// Constructs the generic type and locates the service, then casts to TInterface
         /// </summary>
         /// <example>
+        /// <code>
         ///     GetProcessor&lt;IGenericProcessor&gt;(typeof(GenericProcessor&lt;&gt;), typeof(TResource));
+        /// </code>
         /// </example>
         TInterface GetProcessor<TInterface>(Type openGenericType, Type resourceType);
 
@@ -22,7 +24,9 @@ public interface IGenericProcessorFactory
         /// Constructs the generic type and locates the service, then casts to TInterface
         /// </summary>
         /// <example>
+        /// <code>
         ///     GetProcessor&lt;IGenericProcessor&gt;(typeof(GenericProcessor&lt;,&gt;), typeof(TResource), typeof(TId));
+        /// </code>
         /// </example>
         TInterface GetProcessor<TInterface>(Type openGenericType, Type resourceType, Type keyType);
     }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs
index d7ec6868b9..ce70fced84 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs
@@ -5,6 +5,7 @@
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.TestHost;
 using JsonApiDotNetCore.Services;
+using JsonApiDotNetCore.Data;
 
 namespace JsonApiDotNetCoreExampleTests.Acceptance
 {
@@ -22,7 +23,7 @@ public TestFixture()
             _services = _server.Host.Services;
 
             Client = _server.CreateClient();
-            Context = GetService<AppDbContext>();
+            Context = GetService<IDbContextResolver>().GetContext() as AppDbContext;
             DeSerializer = GetService<IJsonApiDeSerializer>();
             JsonApiContext = GetService<IJsonApiContext>();
         }

From 1bc89eaa1edb3a9cfa6f78d2e909dfd5934c5f55 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 25 Mar 2018 20:36:05 -0500
Subject: [PATCH 105/227] fix(operations test): use update vs replace

---
 test/UnitTests/Services/Operations/OperationsProcessorTests.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
index 5b98927119..9635c6f6f3 100644
--- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -121,7 +121,7 @@ public async Task ProcessAsync_Performs_LocalId_ReplacementAsync_In_References()
                         }
                     }
                 }, {
-                    ""op"": ""replace"",
+                    ""op"": ""update"",
                     ""ref"": {
                         ""type"": ""authors"",
                         ""lid"": ""a""

From 9215ccd7e193e3a95c8197e7ba50c97be8603533 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 27 Mar 2018 06:46:13 -0500
Subject: [PATCH 106/227] introduce ScopedServiceProvider and fix tests

---
 README.md                                     |  1 -
 .../NoEntityFrameworkExample/Startup.cs       |  5 +-
 src/Examples/OperationsExample/Startup.cs     |  5 +-
 src/Examples/ReportsExample/Startup.cs        | 10 +-
 .../Configuration/JsonApiOptions.cs           |  8 +-
 .../Extensions/DbContextExtensions.cs         |  1 -
 .../IServiceCollectionExtensions.cs           |  4 +-
 .../Generics/GenericProcessorFactory.cs       |  5 +-
 .../Services/ScopedServiceProvider.cs         | 28 ++++++
 src/JsonApiDotNetCore/api/.manifest           |  8 +-
 .../CamelCasedModelsControllerTests.cs        | 14 +--
 .../Extensibility/CustomControllerTests.cs    |  4 +-
 .../NullValuedAttributeHandlingTests.cs       |  4 +-
 .../Extensibility/RepositoryOverrideTests.cs  |  4 +-
 .../Extensibility/RequestMetaTests.cs         |  4 +-
 .../Acceptance/Spec/AttributeFilterTests.cs   |  9 +-
 .../Acceptance/Spec/AttributeSortTests.cs     |  4 +-
 .../Acceptance/Spec/ContentNegotiation.cs     |  4 +-
 .../Acceptance/Spec/CreatingDataTests.cs      |  4 +-
 .../Acceptance/Spec/DeletingDataTests.cs      |  8 +-
 .../Acceptance/Spec/DocumentTests/Included.cs |  4 +-
 .../Acceptance/Spec/DocumentTests/Meta.cs     |  4 +-
 .../Spec/DocumentTests/PagingTests.cs         |  4 +-
 .../Spec/DocumentTests/Relationships.cs       |  4 +-
 .../Acceptance/Spec/FetchingDataTests.cs      |  4 +-
 .../Spec/FetchingRelationshipsTests.cs        |  4 +-
 .../Acceptance/Spec/PagingTests.cs            | 15 ++-
 .../Acceptance/Spec/QueryParameters.cs        |  4 +-
 .../Acceptance/Spec/SparseFieldSetTests.cs    |  4 +-
 .../Acceptance/Spec/UpdatingDataTests.cs      |  4 +-
 .../Spec/UpdatingRelationshipsTests.cs        |  4 +-
 .../Acceptance/TodoItemsControllerTests.cs    | 12 +--
 .../Helpers/Startups/AuthorizedStartup.cs     |  8 +-
 .../JsonApiDotNetCoreExampleTests.csproj      |  1 +
 .../TestStartup.cs                            | 22 +++++
 .../IServiceCollectionExtensionsTests.cs      |  7 +-
 .../WebHostCollection.cs                      |  2 +-
 .../Extensibility/NoEntityFrameworkTests.cs   |  5 +-
 .../NoEntityFrameworkTests.csproj             |  1 +
 test/NoEntityFrameworkTests/TestStartup.cs    | 22 +++++
 test/OperationsExampleTests/Add/AddTests.cs   | 29 +++---
 .../{WebHostCollection.cs => Fixture.cs}      | 27 ++++--
 test/OperationsExampleTests/Get/GetTests.cs   | 41 ++++-----
 .../OperationsExampleTests.csproj             |  1 +
 .../Remove/RemoveTests.cs                     | 55 +++++------
 test/OperationsExampleTests/TestStartup.cs    | 25 +++++
 .../Transactions/TransactionFailureTests.cs   | 15 +--
 .../Update/UpdateTests.cs                     | 92 +++++++++----------
 test/UnitTests/TestScopedServiceProvider.cs   | 28 ++++++
 49 files changed, 354 insertions(+), 228 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs
 create mode 100644 test/JsonApiDotNetCoreExampleTests/TestStartup.cs
 create mode 100644 test/NoEntityFrameworkTests/TestStartup.cs
 rename test/OperationsExampleTests/{WebHostCollection.cs => Fixture.cs} (64%)
 create mode 100644 test/OperationsExampleTests/TestStartup.cs
 create mode 100644 test/UnitTests/TestScopedServiceProvider.cs

diff --git a/README.md b/README.md
index 1acbbbf799..f396be824b 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,6 @@
 [![Build status](https://ci.appveyor.com/api/projects/status/9fvgeoxdikwkom10?svg=true)](https://ci.appveyor.com/project/jaredcnance/jsonapidotnetcore)
 [![Travis](https://travis-ci.org/json-api-dotnet/JsonApiDotNetCore.svg?branch=master)](https://travis-ci.org/json-api-dotnet/JsonApiDotNetCore)
 [![NuGet](https://img.shields.io/nuget/v/JsonApiDotNetCore.svg)](https://www.nuget.org/packages/JsonApiDotNetCore/)
-[![MyGet CI](https://img.shields.io/myget/research-institute/vpre/JsonApiDotNetCore.svg)](https://www.myget.org/feed/research-institute/package/nuget/JsonApiDotNetCore)
 [![Join the chat at https://gitter.im/json-api-dotnet-core/Lobby](https://badges.gitter.im/json-api-dotnet-core/Lobby.svg)](https://gitter.im/json-api-dotnet-core/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![FIRST-TIMERS](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](http://www.firsttimersonly.com/)
 
diff --git a/src/Examples/NoEntityFrameworkExample/Startup.cs b/src/Examples/NoEntityFrameworkExample/Startup.cs
index 81f743aa5f..dfba27ddd9 100755
--- a/src/Examples/NoEntityFrameworkExample/Startup.cs
+++ b/src/Examples/NoEntityFrameworkExample/Startup.cs
@@ -9,6 +9,7 @@
 using Microsoft.Extensions.Logging;
 using NoEntityFrameworkExample.Services;
 using Microsoft.EntityFrameworkCore;
+using System;
 
 namespace NoEntityFrameworkExample
 {
@@ -27,7 +28,7 @@ public Startup(IHostingEnvironment env)
         public IConfigurationRoot Configuration { get; }
 
         // This method gets called by the runtime. Use this method to add services to the container.
-        public void ConfigureServices(IServiceCollection services)
+        public virtual IServiceProvider ConfigureServices(IServiceCollection services)
         {
             // Add framework services.
             var mvcBuilder = services.AddMvc();
@@ -46,6 +47,8 @@ public void ConfigureServices(IServiceCollection services)
             services.AddSingleton<IConfiguration>(Configuration);
             services.AddSingleton<DbContextOptions<AppDbContext>>(optionsBuilder.Options);
             services.AddScoped<AppDbContext>();
+
+            return services.BuildServiceProvider();
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
diff --git a/src/Examples/OperationsExample/Startup.cs b/src/Examples/OperationsExample/Startup.cs
index 6e13b2964d..78a6d29f69 100644
--- a/src/Examples/OperationsExample/Startup.cs
+++ b/src/Examples/OperationsExample/Startup.cs
@@ -32,10 +32,7 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
 
             services.AddSingleton<ILoggerFactory>(loggerFactory);
 
-            services.AddDbContext<AppDbContext>(options =>
-            {
-                options.UseNpgsql(GetDbConnectionString());
-            }, ServiceLifetime.Transient);
+            services.AddDbContext<AppDbContext>(options => options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Scoped);
 
             services.AddJsonApi<AppDbContext>(opt => opt.EnableOperations = true);
 
diff --git a/src/Examples/ReportsExample/Startup.cs b/src/Examples/ReportsExample/Startup.cs
index fed3707789..72710681b9 100644
--- a/src/Examples/ReportsExample/Startup.cs
+++ b/src/Examples/ReportsExample/Startup.cs
@@ -1,7 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
 using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Builder;
@@ -9,7 +5,6 @@
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
 
 namespace ReportsExample
 {
@@ -28,12 +23,13 @@ public Startup(IHostingEnvironment env)
             Config = builder.Build();
         }
 
-        public void ConfigureServices(IServiceCollection services)
+        public virtual void ConfigureServices(IServiceCollection services)
         {
             var mvcBuilder = services.AddMvc();
             services.AddJsonApi(opt =>
             {
-                opt.BuildContextGraph(builder => {
+                opt.BuildContextGraph(builder =>
+                {
                     builder.AddResource<Report>("reports");
                 });
                 opt.Namespace = "api";
diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index ea8d0554e3..abcb3f6dbf 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -105,9 +105,13 @@ public class JsonApiOptions
         public NullAttributeResponseBehavior NullAttributeResponseBehavior { get; set; }
 
         /// <summary>
-        /// Whether or not to allow json:api v1.1 operation requests
-        /// This will be enabled by default in JsonApiDotNetCore v2.2.1
+        /// Whether or not to allow json:api v1.1 operation requests.
+        /// This is a beta feature and there may be breaking changes
+        /// in subsequent releases.
         /// </summary>
+        /// <remarks>
+        /// This will be enabled by default in JsonApiDotNetCore v2.2.1
+        /// </remarks>
         public bool EnableOperations { get; set; }
 
         [Obsolete("JsonContract resolver can now be set on SerializerSettings.")]
diff --git a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
index e8b4e3d601..2606342e29 100644
--- a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
@@ -1,5 +1,4 @@
 using Microsoft.EntityFrameworkCore;
-using System.Reflection;
 using System;
 
 namespace JsonApiDotNetCore.Extensions
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 604d65536b..0b13755edc 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -6,7 +6,6 @@
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Middleware;
-using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
 using JsonApiDotNetCore.Services.Operations;
@@ -89,7 +88,7 @@ public static void AddJsonApiInternals(
             this IServiceCollection services,
             JsonApiOptions jsonApiOptions)
         {
-            if (!jsonApiOptions.ContextGraph.UsesDbContext)
+            if (jsonApiOptions.ContextGraph.UsesDbContext == false)
             {
                 services.AddScoped<DbContext>();
                 services.AddSingleton<DbContextOptions>(new DbContextOptionsBuilder().Options);
@@ -122,6 +121,7 @@ public static void AddJsonApiInternals(
             services.AddSingleton<IContextGraph>(jsonApiOptions.ContextGraph);
             services.AddScoped<IJsonApiContext, JsonApiContext>();
             services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
+            services.AddScoped<IScopedServiceProvider, RequestScopedServiceProvider>();
             services.AddScoped<JsonApiRouteHandler>();
             services.AddScoped<IMetaBuilder, MetaBuilder>();
             services.AddScoped<IDocumentBuilder, DocumentBuilder>();
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
index 27d15b163d..08cba58dd1 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
@@ -1,3 +1,4 @@
+using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
 using System;
 
@@ -35,9 +36,9 @@ public class GenericProcessorFactory : IGenericProcessorFactory
     {
         private readonly IServiceProvider _serviceProvider;
 
-        public GenericProcessorFactory(IHttpContextAccessor httpContextAccessor)
+        public GenericProcessorFactory(IScopedServiceProvider serviceProvider)
         {
-            _serviceProvider = httpContextAccessor.HttpContext.RequestServices;
+            _serviceProvider = serviceProvider;
         }
 
         public TInterface GetProcessor<TInterface>(Type openGenericType, Type resourceType)
diff --git a/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs b/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs
new file mode 100644
index 0000000000..38e147645f
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs
@@ -0,0 +1,28 @@
+using Microsoft.AspNetCore.Http;
+using System;
+
+namespace JsonApiDotNetCore.Services
+{
+    /// <summary>
+    /// An interface used to separate the registration of the global ServiceProvider
+    /// from a request scoped service provider. This is useful in cases when we need to 
+    /// manually resolve services from the request scope (e.g. operation processors)
+    /// </summary>
+    public interface IScopedServiceProvider : IServiceProvider { }
+
+    /// <summary>
+    /// A service provider that uses the current HttpContext request scope
+    /// </summary>
+    public class RequestScopedServiceProvider : IScopedServiceProvider
+    {
+        private readonly IServiceProvider _serviceProvider;
+
+        public RequestScopedServiceProvider(IHttpContextAccessor httpContextAccessor)
+        {
+            _serviceProvider = httpContextAccessor.HttpContext.RequestServices;
+        }
+
+        /// <inheritdoc />
+        public object GetService(Type serviceType) => _serviceProvider.GetService(serviceType);
+    }
+}
diff --git a/src/JsonApiDotNetCore/api/.manifest b/src/JsonApiDotNetCore/api/.manifest
index 632c57f5eb..6aa4a40924 100644
--- a/src/JsonApiDotNetCore/api/.manifest
+++ b/src/JsonApiDotNetCore/api/.manifest
@@ -283,7 +283,7 @@
   "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.SetRelationships(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
-  "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.#ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
+  "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.#ctor(JsonApiDotNetCore.Services.IScopedServiceProvider)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.GetProcessor``1(System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.GetProcessor``1(System.Type,System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml",
   "JsonApiDotNetCore.Internal.Generics.IGenericProcessor": "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.yml",
@@ -586,6 +586,7 @@
   "JsonApiDotNetCore.Services.IResourceQueryService`2": "JsonApiDotNetCore.Services.IResourceQueryService-2.yml",
   "JsonApiDotNetCore.Services.IResourceService`1": "JsonApiDotNetCore.Services.IResourceService-1.yml",
   "JsonApiDotNetCore.Services.IResourceService`2": "JsonApiDotNetCore.Services.IResourceService-2.yml",
+  "JsonApiDotNetCore.Services.IScopedServiceProvider": "JsonApiDotNetCore.Services.IScopedServiceProvider.yml",
   "JsonApiDotNetCore.Services.IUpdateRelationshipService`1": "JsonApiDotNetCore.Services.IUpdateRelationshipService-1.yml",
   "JsonApiDotNetCore.Services.IUpdateRelationshipService`2": "JsonApiDotNetCore.Services.IUpdateRelationshipService-2.yml",
   "JsonApiDotNetCore.Services.IUpdateRelationshipService`2.UpdateRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Services.IUpdateRelationshipService-2.yml",
@@ -673,5 +674,8 @@
   "JsonApiDotNetCore.Services.QueryParser.ParseFilterQuery(System.String,System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
   "JsonApiDotNetCore.Services.QueryParser.ParseIncludedRelationships(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
   "JsonApiDotNetCore.Services.QueryParser.ParsePageQuery(JsonApiDotNetCore.Internal.Query.PageQuery,System.String,System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
-  "JsonApiDotNetCore.Services.QueryParser.ParseSortParameters(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml"
+  "JsonApiDotNetCore.Services.QueryParser.ParseSortParameters(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml",
+  "JsonApiDotNetCore.Services.RequestScopedServiceProvider": "JsonApiDotNetCore.Services.RequestScopedServiceProvider.yml",
+  "JsonApiDotNetCore.Services.RequestScopedServiceProvider.#ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor)": "JsonApiDotNetCore.Services.RequestScopedServiceProvider.yml",
+  "JsonApiDotNetCore.Services.RequestScopedServiceProvider.GetService(System.Type)": "JsonApiDotNetCore.Services.RequestScopedServiceProvider.yml"
 }
\ No newline at end of file
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs
index b76293adba..533c59839a 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Net;
 using System.Net.Http;
 using System.Net.Http.Headers;
@@ -19,12 +19,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance
     [Collection("WebHostCollection")]
     public class CamelCasedModelsControllerTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
         private IJsonApiContext _jsonApiContext;
         private Faker<CamelCasedModel> _faker;
 
-        public CamelCasedModelsControllerTests(TestFixture<Startup> fixture)
+        public CamelCasedModelsControllerTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
@@ -58,7 +58,7 @@ public async Task Can_Get_CamelCasedModels()
             // Assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotEmpty(deserializedBody);
-            Assert.True(deserializedBody.Count >  0);
+            Assert.True(deserializedBody.Count > 0);
         }
 
         [Fact]
@@ -114,7 +114,7 @@ public async Task Can_Post_CamelCasedModels()
             var request = new HttpRequestMessage(httpMethod, route);
             request.Content = new StringContent(JsonConvert.SerializeObject(content));
             request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
-            
+
             // Act
             var response = await client.SendAsync(request);
             var body = await response.Content.ReadAsStringAsync();
@@ -158,7 +158,7 @@ public async Task Can_Patch_CamelCasedModels()
             var request = new HttpRequestMessage(httpMethod, route);
             request.Content = new StringContent(JsonConvert.SerializeObject(content));
             request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
-            
+
             // Act
             var response = await client.SendAsync(request);
             var body = await response.Content.ReadAsStringAsync();
@@ -173,4 +173,4 @@ public async Task Can_Patch_CamelCasedModels()
             Assert.Equal(newModel.CompoundAttr, deserializedBody.CompoundAttr);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs
index 9b28ee48de..478f40f14f 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs
@@ -17,11 +17,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility
     [Collection("WebHostCollection")]
     public class CustomControllerTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private Faker<TodoItem> _todoItemFaker;
         private Faker<Person> _personFaker;
 
-        public CustomControllerTests(TestFixture<Startup> fixture)
+        public CustomControllerTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _todoItemFaker = new Faker<TodoItem>()
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs
index 250ab80d30..7942ffd919 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs
@@ -14,11 +14,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility
     [Collection("WebHostCollection")]
     public class NullValuedAttributeHandlingTests : IAsyncLifetime
     {
-        private readonly TestFixture<Startup> _fixture;
+        private readonly TestFixture<TestStartup> _fixture;
         private readonly AppDbContext _dbContext;
         private readonly TodoItem _todoItem;
 
-        public NullValuedAttributeHandlingTests(TestFixture<Startup> fixture)
+        public NullValuedAttributeHandlingTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _dbContext = fixture.GetService<AppDbContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
index 2813151ad3..09a2791048 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
@@ -17,9 +17,9 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility
     [Collection("WebHostCollection")]
     public class RepositoryOverrideTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
 
-        public RepositoryOverrideTests(TestFixture<Startup> fixture)
+        public RepositoryOverrideTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs
index 9420ea6891..2397bb5529 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs
@@ -16,9 +16,9 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility
     [Collection("WebHostCollection")]
     public class RequestMetaTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
 
-        public RequestMetaTests(TestFixture<Startup> fixture)
+        public RequestMetaTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index dd7c673b4c..083b2c22d7 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
@@ -6,7 +6,6 @@
 using Bogus;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Serialization;
-using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using Newtonsoft.Json;
@@ -18,11 +17,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class AttributeFilterTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private Faker<TodoItem> _todoItemFaker;
         private readonly Faker<Person> _personFaker;
 
-        public AttributeFilterTests(TestFixture<Startup> fixture)
+        public AttributeFilterTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _todoItemFaker = new Faker<TodoItem>()
@@ -88,7 +87,7 @@ public async Task Can_Filter_On_Related_Attrs()
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotNull(included);
             Assert.NotEmpty(included);
-            foreach(var item in included)
+            foreach (var item in included)
                 Assert.Equal(person.FirstName, item.Attributes["first-name"]);
         }
 
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs
index 8525f251d1..6de3293596 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs
@@ -9,9 +9,9 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class AttributeSortTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
 
-        public AttributeSortTests(TestFixture<Startup> fixture)
+        public AttributeSortTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs
index 8f76735ee9..76f5fa4aa7 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs
@@ -12,8 +12,8 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class ContentNegotiation
     {
-        private TestFixture<Startup> _fixture;
-        public ContentNegotiation(TestFixture<Startup> fixture)
+        private TestFixture<TestStartup> _fixture;
+        public ContentNegotiation(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
index 2f461c4f74..2c71275473 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
@@ -23,11 +23,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class CreatingDataTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private IJsonApiContext _jsonApiContext;
         private Faker<TodoItem> _todoItemFaker;
 
-        public CreatingDataTests(TestFixture<Startup> fixture)
+        public CreatingDataTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _jsonApiContext = fixture.GetService<IJsonApiContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs
index 8ddb9a56a1..8c506f4a33 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
 using System.Net;
 using System.Net.Http;
 using System.Threading.Tasks;
@@ -15,11 +15,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class DeletingDataTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
         private Faker<TodoItem> _todoItemFaker;
 
-        public DeletingDataTests(TestFixture<Startup> fixture)
+        public DeletingDataTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
@@ -40,7 +40,7 @@ public async Task Respond_404_If_EntityDoesNotExist()
 
             var server = new TestServer(builder);
             var client = server.CreateClient();
-    
+
             var httpMethod = new HttpMethod("DELETE");
             var route = $"/api/v1/todo-items/{maxPersonId + 100}";
             var request = new HttpRequestMessage(httpMethod, route);
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
index 5d4a4aa4e2..a9aa9c4e67 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
@@ -19,13 +19,13 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests
     [Collection("WebHostCollection")]
     public class Included
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
         private Bogus.Faker<Person> _personFaker;
         private Faker<TodoItem> _todoItemFaker;
         private Faker<TodoItemCollection> _todoItemCollectionFaker;
 
-        public Included(TestFixture<Startup> fixture)
+        public Included(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
index 5316753245..bb055e9935 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
@@ -17,9 +17,9 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests
     [Collection("WebHostCollection")]
     public class Meta
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
-        public Meta(TestFixture<Startup> fixture)
+        public Meta(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
index 0aa4ede88b..787c9f07a0 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
@@ -18,13 +18,13 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests
     [Collection("WebHostCollection")]
     public class PagingTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
         private Faker<Person> _personFaker;
         private Faker<TodoItem> _todoItemFaker;
         private Faker<TodoItemCollection> _todoItemCollectionFaker;
 
-        public PagingTests(TestFixture<Startup> fixture)
+        public PagingTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs
index 5c0018354d..6c4bf56839 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs
@@ -17,11 +17,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests
     [Collection("WebHostCollection")]
     public class Relationships
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
         private Faker<TodoItem> _todoItemFaker;
 
-        public Relationships(TestFixture<Startup> fixture)
+        public Relationships(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs
index 208ec2f72d..8573d0b560 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs
@@ -20,12 +20,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class FetchingDataTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private IJsonApiContext _jsonApiContext;
         private Faker<TodoItem> _todoItemFaker;
         private Faker<Person> _personFaker;
 
-        public FetchingDataTests(TestFixture<Startup> fixture)
+        public FetchingDataTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _jsonApiContext = fixture.GetService<IJsonApiContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
index ea805c515f..621cb8e349 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
@@ -16,11 +16,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class FetchingRelationshipsTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private IJsonApiContext _jsonApiContext;
         private Faker<TodoItem> _todoItemFaker;
 
-        public FetchingRelationshipsTests(TestFixture<Startup> fixture)
+        public FetchingRelationshipsTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _jsonApiContext = fixture.GetService<IJsonApiContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
index 7d8401f78d..2d77982e62 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
@@ -10,15 +10,18 @@
 using Xunit;
 using Person = JsonApiDotNetCoreExample.Models.Person;
 
-namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec {
-    public class PagingTests : TestFixture<Startup> {
+namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
+{
+    public class PagingTests : TestFixture<TestStartup>
+    {
         private readonly Faker<TodoItem> _todoItemFaker = new Faker<TodoItem>()
             .RuleFor(t => t.Description, f => f.Lorem.Sentence())
             .RuleFor(t => t.Ordinal, f => f.Random.Number())
             .RuleFor(t => t.CreatedDate, f => f.Date.Past());
 
         [Fact]
-        public async Task Can_Paginate_TodoItems() {
+        public async Task Can_Paginate_TodoItems()
+        {
             // Arrange
             const int expectedEntitiesPerPage = 2;
             var totalCount = expectedEntitiesPerPage * 2;
@@ -47,7 +50,8 @@ public async Task Can_Paginate_TodoItems() {
         }
 
         [Fact]
-        public async Task Can_Paginate_TodoItems_From_Start() {
+        public async Task Can_Paginate_TodoItems_From_Start()
+        {
             // Arrange
             const int expectedEntitiesPerPage = 2;
             var totalCount = expectedEntitiesPerPage * 2;
@@ -77,7 +81,8 @@ public async Task Can_Paginate_TodoItems_From_Start() {
         }
 
         [Fact]
-        public async Task Can_Paginate_TodoItems_From_End() {
+        public async Task Can_Paginate_TodoItems_From_End()
+        {
             // Arrange
             const int expectedEntitiesPerPage = 2;
             var totalCount = expectedEntitiesPerPage * 2;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs
index c5a02cb6b7..f5f61e156d 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs
@@ -13,8 +13,8 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class QueryParameters
     {
-        private TestFixture<Startup> _fixture;
-        public QueryParameters(TestFixture<Startup> fixture)
+        private TestFixture<TestStartup> _fixture;
+        public QueryParameters(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs
index 8c5c6b5249..7286a94fc5 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs
@@ -21,10 +21,10 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class SparseFieldSetTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private readonly AppDbContext _dbContext;
 
-        public SparseFieldSetTests(TestFixture<Startup> fixture)
+        public SparseFieldSetTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _dbContext = fixture.GetService<AppDbContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs
index d39f69a855..36ea085508 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs
@@ -20,12 +20,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class UpdatingDataTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
         private Faker<TodoItem> _todoItemFaker;
         private Faker<Person> _personFaker;
 
-        public UpdatingDataTests(TestFixture<Startup> fixture)
+        public UpdatingDataTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
index 5cc3772497..1dffa6ce87 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
@@ -20,12 +20,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
     [Collection("WebHostCollection")]
     public class UpdatingRelationshipsTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
         private Bogus.Faker<Person> _personFaker;
         private Faker<TodoItem> _todoItemFaker;
 
-        public UpdatingRelationshipsTests(TestFixture<Startup> fixture)
+        public UpdatingRelationshipsTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
index 657e282cb8..acd37a535a 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
@@ -19,12 +19,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance
     [Collection("WebHostCollection")]
     public class TodoItemControllerTests
     {
-        private TestFixture<Startup> _fixture;
+        private TestFixture<TestStartup> _fixture;
         private AppDbContext _context;
         private IJsonApiContext _jsonApiContext;
         private Faker<TodoItem> _todoItemFaker;
 
-        public TodoItemControllerTests(TestFixture<Startup> fixture)
+        public TodoItemControllerTests(TestFixture<TestStartup> fixture)
         {
             _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
@@ -75,7 +75,7 @@ public async Task Can_Filter_TodoItems()
             var httpMethod = new HttpMethod("GET");
             var route = $"/api/v1/todo-items?filter[ordinal]={todoItem.Ordinal}";
             var request = new HttpRequestMessage(httpMethod, route);
-            
+
             // Act
             var response = await _fixture.Client.SendAsync(request);
             var body = await response.Content.ReadAsStringAsync();
@@ -339,7 +339,7 @@ public async Task Can_Patch_TodoItem()
             var request = new HttpRequestMessage(httpMethod, route);
             request.Content = new StringContent(JsonConvert.SerializeObject(content));
             request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
-            
+
             // Act
             var response = await _fixture.Client.SendAsync(request);
             var body = await response.Content.ReadAsStringAsync();
@@ -484,4 +484,4 @@ public async Task Can_Delete_TodoItem()
             Assert.Null(_context.TodoItems.FirstOrDefault(t => t.Id == todoItem.Id));
         }
     }
-}
\ No newline at end of file
+}
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/AuthorizedStartup.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/AuthorizedStartup.cs
index 21cfa0e0dc..12a207fea8 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/AuthorizedStartup.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/AuthorizedStartup.cs
@@ -11,14 +11,16 @@
 using JsonApiDotNetCore.Data;
 using JsonApiDotNetCoreExample.Models;
 using JsonApiDotNetCoreExampleTests.Repositories;
+using UnitTests;
+using JsonApiDotNetCore.Services;
 
 namespace JsonApiDotNetCoreExampleTests.Startups
 {
     public class AuthorizedStartup : Startup
     {
         public AuthorizedStartup(IHostingEnvironment env)
-        : base (env)
-        {  }        
+        : base(env)
+        { }
 
         public override IServiceProvider ConfigureServices(IServiceCollection services)
         {
@@ -46,6 +48,8 @@ public override IServiceProvider ConfigureServices(IServiceCollection services)
             services.AddSingleton<IAuthorizationService>(authServicMock.Object);
             services.AddScoped<IEntityRepository<TodoItem>, AuthorizedTodoItemsRepository>();
 
+            services.AddScoped<IScopedServiceProvider, TestScopedServiceProvider>();
+
             return services.BuildServiceProvider();
         }
     }
diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
index 90bd4050e7..b1df354bf7 100755
--- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
@@ -13,6 +13,7 @@
   <ItemGroup>
     <ProjectReference Include="../../src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj" />
     <ProjectReference Include="../../src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj" />
+    <ProjectReference Include="..\UnitTests\UnitTests.csproj" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/test/JsonApiDotNetCoreExampleTests/TestStartup.cs b/test/JsonApiDotNetCoreExampleTests/TestStartup.cs
new file mode 100644
index 0000000000..886d6b3424
--- /dev/null
+++ b/test/JsonApiDotNetCoreExampleTests/TestStartup.cs
@@ -0,0 +1,22 @@
+using JsonApiDotNetCore.Services;
+using JsonApiDotNetCoreExample;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using UnitTests;
+
+namespace JsonApiDotNetCoreExampleTests
+{
+    public class TestStartup : Startup
+    {
+        public TestStartup(IHostingEnvironment env) : base(env)
+        { }
+
+        public override IServiceProvider ConfigureServices(IServiceCollection services)
+        {
+            base.ConfigureServices(services);
+            services.AddScoped<IScopedServiceProvider, TestScopedServiceProvider>();
+            return services.BuildServiceProvider();
+        }
+    }
+}
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs b/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
index b654727a26..f6772fa22b 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
@@ -10,9 +10,9 @@
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using Microsoft.AspNetCore.Http;
-using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.Caching.Memory;
 using Microsoft.Extensions.DependencyInjection;
+using UnitTests;
 using Xunit;
 
 namespace JsonApiDotNetCoreExampleTests.Unit.Extensions
@@ -25,7 +25,7 @@ public void AddJsonApiInternals_Adds_All_Required_Services()
             // arrange
             var services = new ServiceCollection();
             var jsonApiOptions = new JsonApiOptions();
-            
+
             services.AddDbContext<AppDbContext>(options =>
             {
                 options.UseMemoryCache(new MemoryCache(new MemoryCacheOptions()));
@@ -33,6 +33,9 @@ public void AddJsonApiInternals_Adds_All_Required_Services()
 
             // act
             services.AddJsonApiInternals<AppDbContext>(jsonApiOptions);
+            // this is required because the DbContextResolver requires access to the current HttpContext
+            // to get the request scoped DbContext instance
+            services.AddScoped<IScopedServiceProvider, TestScopedServiceProvider>();
             var provider = services.BuildServiceProvider();
 
             // assert
diff --git a/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs b/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
index 43a89616df..960b7c1e46 100644
--- a/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
+++ b/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
@@ -6,6 +6,6 @@ namespace JsonApiDotNetCoreExampleTests
 {
     [CollectionDefinition("WebHostCollection")]
     public class WebHostCollection
-        : ICollectionFixture<TestFixture<Startup>>
+        : ICollectionFixture<TestFixture<TestStartup>>
     { }
 }
diff --git a/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs b/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs
index 41a48f2743..e80acc5d50 100644
--- a/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs
+++ b/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs
@@ -10,7 +10,6 @@
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.TestHost;
 using Newtonsoft.Json;
-using NoEntityFrameworkExample;
 using Xunit;
 
 namespace NoEntityFrameworkTests.Acceptance.Extensibility
@@ -23,7 +22,7 @@ public class NoEntityFrameworkTests
         public NoEntityFrameworkTests()
         {
             var builder = new WebHostBuilder()
-                .UseStartup<Startup>();
+                .UseStartup<TestStartup>();
             _server = new TestServer(builder);
             _context = _server.GetService<AppDbContext>();
             _context.Database.EnsureCreated();
@@ -97,7 +96,7 @@ public async Task Can_Create_TodoItems()
                     type = "custom-todo-items",
                     attributes = new
                     {
-                        description = description,
+                        description,
                         ordinal = 1
                     }
                 }
diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
index 646cf9d538..f1d4044e0b 100644
--- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
+++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
@@ -17,6 +17,7 @@
     <ProjectReference Include="../../src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj" />
     <ProjectReference Include="../../test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj" />
     <ProjectReference Include="../../src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj" />
+    <ProjectReference Include="..\UnitTests\UnitTests.csproj" />
   </ItemGroup>
   <ItemGroup>
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
diff --git a/test/NoEntityFrameworkTests/TestStartup.cs b/test/NoEntityFrameworkTests/TestStartup.cs
new file mode 100644
index 0000000000..e925e69fd0
--- /dev/null
+++ b/test/NoEntityFrameworkTests/TestStartup.cs
@@ -0,0 +1,22 @@
+using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using NoEntityFrameworkExample;
+using System;
+using UnitTests;
+
+namespace NoEntityFrameworkTests
+{
+    public class TestStartup : Startup
+    {
+        public TestStartup(IHostingEnvironment env) : base(env)
+        { }
+
+        public override IServiceProvider ConfigureServices(IServiceCollection services)
+        {
+            base.ConfigureServices(services);
+            services.AddScoped<IScopedServiceProvider, TestScopedServiceProvider>();
+            return services.BuildServiceProvider();
+        }
+    }
+}
diff --git a/test/OperationsExampleTests/Add/AddTests.cs b/test/OperationsExampleTests/Add/AddTests.cs
index 656cb134b5..2390973594 100644
--- a/test/OperationsExampleTests/Add/AddTests.cs
+++ b/test/OperationsExampleTests/Add/AddTests.cs
@@ -11,22 +11,15 @@
 
 namespace OperationsExampleTests
 {
-    [Collection("WebHostCollection")]
-    public class AddTests
+    public class AddTests : Fixture
     {
-        private readonly Fixture _fixture;
         private readonly Faker _faker = new Faker();
 
-        public AddTests(Fixture fixture)
-        {
-            _fixture = fixture;
-        }
-
         [Fact]
         public async Task Can_Create_Author()
         {
             // arrange
-            var context = _fixture.GetService<AppDbContext>();
+            var context = GetService<AppDbContext>();
             var author = AuthorFactory.Get();
             var content = new
             {
@@ -44,13 +37,13 @@ public async Task Can_Create_Author()
             };
 
             // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(result.response);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.NotNull(response);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
 
-            var id = result.data.Operations.Single().DataObject.Id;
+            var id = data.Operations.Single().DataObject.Id;
             var lastAuthor = await context.Authors.SingleAsync(a => a.StringId == id);
             Assert.Equal(author.Name, lastAuthor.Name);
         }
@@ -60,7 +53,7 @@ public async Task Can_Create_Authors()
         {
             // arrange
             var expectedCount = _faker.Random.Int(1, 10);
-            var context = _fixture.GetService<AppDbContext>();
+            var context = GetService<AppDbContext>();
             var authors = AuthorFactory.Get(expectedCount);
             var content = new
             {
@@ -86,7 +79,7 @@ public async Task Can_Create_Authors()
             }
 
             // act
-            var (response, data) = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
             Assert.NotNull(response);
@@ -96,7 +89,7 @@ public async Task Can_Create_Authors()
             for (int i = 0; i < expectedCount; i++)
             {
                 var dataObject = data.Operations[i].DataObject;
-                var author = context.Authors.Single(a => a.StringId == dataObject.ToString());
+                var author = context.Authors.Single(a => a.StringId == dataObject.Id);
                 Assert.Equal(authors[i].Name, author.Name);
             }
         }
@@ -105,7 +98,7 @@ public async Task Can_Create_Authors()
         public async Task Can_Create_Author_With_Article()
         {
             // arrange
-            var context = _fixture.GetService<AppDbContext>();
+            var context = GetService<AppDbContext>();
             var author = AuthorFactory.Get();
             var article = ArticleFactory.Get();
             const string authorLocalId = "author-1";
@@ -144,7 +137,7 @@ public async Task Can_Create_Author_With_Article()
             };
 
             // act
-            var (response, data) = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
             Assert.NotNull(response);
diff --git a/test/OperationsExampleTests/WebHostCollection.cs b/test/OperationsExampleTests/Fixture.cs
similarity index 64%
rename from test/OperationsExampleTests/WebHostCollection.cs
rename to test/OperationsExampleTests/Fixture.cs
index e385ace992..5a594940af 100644
--- a/test/OperationsExampleTests/WebHostCollection.cs
+++ b/test/OperationsExampleTests/Fixture.cs
@@ -1,29 +1,42 @@
+using System;
 using System.Net.Http;
 using System.Net.Http.Headers;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.TestHost;
 using Newtonsoft.Json;
-using OperationsExample;
+using OperationsExample.Data;
 using Xunit;
 
+[assembly: CollectionBehavior(DisableTestParallelization = true)]
 namespace OperationsExampleTests
 {
-    [CollectionDefinition("WebHostCollection")]
-    public class WebHostCollection : ICollectionFixture<Fixture>
-    { }
-
-    public class Fixture
+    public class Fixture : IDisposable
     {
         public Fixture()
         {
-            var builder = new WebHostBuilder().UseStartup<Startup>();
+            var builder = new WebHostBuilder().UseStartup<TestStartup>();
             Server = new TestServer(builder);
             Client = Server.CreateClient();
         }
 
         public TestServer Server { get; private set; }
         public HttpClient Client { get; }
+
+        public void Dispose()
+        {
+            try
+            {
+                var context = GetService<AppDbContext>();
+                context.Articles.RemoveRange(context.Articles);
+                context.Authors.RemoveRange(context.Authors);
+                context.SaveChanges();
+            } // it is possible the test may try to do something that is an invalid db operation
+              // validation should be left up to the test, so we should not bomb the run in the
+              // disposal of that context
+            catch (Exception) { }
+        }
+
         public T GetService<T>() => (T)Server.Host.Services.GetService(typeof(T));
 
         public async Task<HttpResponseMessage> PatchAsync(string route, object data)
diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs
index 17c868cebd..efc06424ce 100644
--- a/test/OperationsExampleTests/Get/GetTests.cs
+++ b/test/OperationsExampleTests/Get/GetTests.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net;
@@ -10,26 +11,20 @@
 
 namespace OperationsExampleTests
 {
-    [Collection("WebHostCollection")]
-    public class GetTests
+    public class GetTests : Fixture, IDisposable
     {
-        private readonly Fixture _fixture;
-        private readonly Faker _faker = new Faker();
-
-        public GetTests(Fixture fixture)
-        {
-            _fixture = fixture;
-        }
+        private readonly Faker _faker = new Faker();
 
         [Fact]
-        public async Task Can_Get_Articles()
+        public async Task Can_Get_Authors()
         {
             // arrange
             var expectedCount = _faker.Random.Int(1, 10);
-            var context = _fixture.GetService<AppDbContext>();
+            var context = GetService<AppDbContext>();
             context.Articles.RemoveRange(context.Articles);
-            var articles = ArticleFactory.Get(expectedCount);
-            context.AddRange(articles);
+            context.Authors.RemoveRange(context.Authors);
+            var authors = AuthorFactory.Get(expectedCount);
+            context.AddRange(authors);
             context.SaveChanges();
 
             var content = new
@@ -37,13 +32,13 @@ public async Task Can_Get_Articles()
                 operations = new[] {
                     new Dictionary<string, object> {
                         { "op", "get"},
-                        { "ref",  new { type = "articles" } }
+                        { "ref",  new { type = "authors" } }
                     }
                 }
             };
 
             // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var result = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
             Assert.NotNull(result.response);
@@ -54,12 +49,12 @@ public async Task Can_Get_Articles()
         }
 
         [Fact]
-        public async Task Can_Get_Article_By_Id()
+        public async Task Can_Get_Author_By_Id()
         {
             // arrange
-            var context = _fixture.GetService<AppDbContext>();
-            var article = ArticleFactory.Get();
-            context.Articles.Add(article);
+            var context = GetService<AppDbContext>();
+            var author = AuthorFactory.Get();
+            context.Authors.Add(author);
             context.SaveChanges();
 
             var content = new
@@ -67,20 +62,20 @@ public async Task Can_Get_Article_By_Id()
                 operations = new[] {
                     new Dictionary<string, object> {
                         { "op", "get"},
-                        { "ref",  new { type = "articles", id = article.StringId } }
+                        { "ref",  new { type = "authors", id = author.StringId } }
                     }
                 }
             };
 
             // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var result = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
             Assert.NotNull(result.response);
             Assert.NotNull(result.data);
             Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
             Assert.Equal(1, result.data.Operations.Count);
-            Assert.Equal(article.Id.ToString(), result.data.Operations.Single().DataObject.Id);
-        }
+            Assert.Equal(author.Id.ToString(), result.data.Operations.Single().DataObject.Id);
+        }
     }
 }
diff --git a/test/OperationsExampleTests/OperationsExampleTests.csproj b/test/OperationsExampleTests/OperationsExampleTests.csproj
index a7727475bd..13f68faf5a 100644
--- a/test/OperationsExampleTests/OperationsExampleTests.csproj
+++ b/test/OperationsExampleTests/OperationsExampleTests.csproj
@@ -14,6 +14,7 @@
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\src\Examples\OperationsExample\OperationsExample.csproj" />
+    <ProjectReference Include="..\UnitTests\UnitTests.csproj" />
   </ItemGroup>
   <ItemGroup>
     <None Update="xunit.runner.json;appsettings.json">
diff --git a/test/OperationsExampleTests/Remove/RemoveTests.cs b/test/OperationsExampleTests/Remove/RemoveTests.cs
index f5229ebbd5..ae647f13b9 100644
--- a/test/OperationsExampleTests/Remove/RemoveTests.cs
+++ b/test/OperationsExampleTests/Remove/RemoveTests.cs
@@ -10,24 +10,17 @@
 
 namespace OperationsExampleTests
 {
-    [Collection("WebHostCollection")]
-    public class RemoveTests
-    {
-        private readonly Fixture _fixture;
+    public class RemoveTests : Fixture
+    {
         private readonly Faker _faker = new Faker();
 
-        public RemoveTests(Fixture fixture)
-        {
-            _fixture = fixture;
-        }
-
         [Fact]
-        public async Task Can_Remove_Article()
+        public async Task Can_Remove_Author()
         {
             // arrange
-            var context = _fixture.GetService<AppDbContext>();
-            var article = ArticleFactory.Get();
-            context.Articles.Add(article);
+            var context = GetService<AppDbContext>();
+            var author = AuthorFactory.Get();
+            context.Authors.Add(author);
             context.SaveChanges();
 
             var content = new
@@ -35,32 +28,32 @@ public async Task Can_Remove_Article()
                 operations = new[] {
                     new Dictionary<string, object> {
                         { "op", "remove"},
-                        { "ref",  new { type = "articles", id = article.StringId } }
+                        { "ref",  new { type = "authors", id = author.StringId } }
                     }
                 }
             };
 
             // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(result.response);
-            Assert.NotNull(result.data);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(1, result.data.Operations.Count);
-            Assert.Null(context.Articles.SingleOrDefault(a => a.Id == article.Id));
+            Assert.NotNull(response);
+            Assert.NotNull(data);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Empty(data.Operations);
+            Assert.Null(context.Authors.SingleOrDefault(a => a.Id == author.Id));
         }
 
         [Fact]
-        public async Task Can_Remove_Articles()
+        public async Task Can_Remove_Authors()
         {
             // arrange
             var count = _faker.Random.Int(1, 10);
-            var context = _fixture.GetService<AppDbContext>();
+            var context = GetService<AppDbContext>();
 
-            var articles = ArticleFactory.Get(count);
+            var authors = AuthorFactory.Get(count);
 
-            context.Articles.AddRange(articles);
+            context.Authors.AddRange(authors);
             context.SaveChanges();
 
             var content = new
@@ -72,21 +65,21 @@ public async Task Can_Remove_Articles()
                 content.operations.Add(
                     new Dictionary<string, object> {
                         { "op", "remove"},
-                        { "ref",  new { type = "articles", id = articles[i].StringId } }
+                        { "ref",  new { type = "authors", id = authors[i].StringId } }
                     }
                 );
 
             // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(result.response);
-            Assert.NotNull(result.data);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(count, result.data.Operations.Count);
+            Assert.NotNull(response);
+            Assert.NotNull(data);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Empty(data.Operations);
 
             for (int i = 0; i < count; i++)
-                Assert.Null(context.Articles.SingleOrDefault(a => a.Id == articles[i].Id));
+                Assert.Null(context.Authors.SingleOrDefault(a => a.Id == authors[i].Id));
         }
     }
 }
diff --git a/test/OperationsExampleTests/TestStartup.cs b/test/OperationsExampleTests/TestStartup.cs
new file mode 100644
index 0000000000..26ee1fdbc3
--- /dev/null
+++ b/test/OperationsExampleTests/TestStartup.cs
@@ -0,0 +1,25 @@
+using JsonApiDotNetCore.Data;
+using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using OperationsExample;
+using OperationsExample.Data;
+using System;
+using UnitTests;
+
+namespace OperationsExampleTests
+{
+    public class TestStartup : Startup
+    {
+        public TestStartup(IHostingEnvironment env) : base(env)
+        { }
+
+        public override IServiceProvider ConfigureServices(IServiceCollection services)
+        {
+            base.ConfigureServices(services);
+            services.AddScoped<IScopedServiceProvider, TestScopedServiceProvider>();
+            services.AddSingleton<IDbContextResolver, DbContextResolver<AppDbContext>>();
+            return services.BuildServiceProvider();
+        }
+    }
+}
diff --git a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
index 53b1e37b5a..635b9b89e4 100644
--- a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
+++ b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
@@ -1,8 +1,6 @@
 using System;
-using System.Diagnostics;
 using System.Linq;
 using System.Net;
-using System.Threading;
 using System.Threading.Tasks;
 using Bogus;
 using JsonApiDotNetCore.Internal;
@@ -13,22 +11,15 @@
 
 namespace OperationsExampleTests
 {
-    [Collection("WebHostCollection")]
-    public class TransactionFailureTests
+    public class TransactionFailureTests : Fixture
     {
-        private readonly Fixture _fixture;
         private readonly Faker _faker = new Faker();
 
-        public TransactionFailureTests(Fixture fixture)
-        {
-            _fixture = fixture;
-        }
-
         [Fact]
         public async Task Cannot_Create_Author_If_Article_Creation_Fails()
         {
             // arrange
-            var context = _fixture.GetService<AppDbContext>();
+            var context = GetService<AppDbContext>();
             var author = AuthorFactory.Get();
             var article = ArticleFactory.Get();
 
@@ -70,7 +61,7 @@ public async Task Cannot_Create_Author_If_Article_Creation_Fails()
             };
 
             // act
-            var (response, data) = await _fixture.PatchAsync<ErrorCollection>("api/bulk", content);
+            var (response, data) = await PatchAsync<ErrorCollection>("api/bulk", content);
 
             // assert
             Assert.NotNull(response);
diff --git a/test/OperationsExampleTests/Update/UpdateTests.cs b/test/OperationsExampleTests/Update/UpdateTests.cs
index de05881963..5538fa5830 100644
--- a/test/OperationsExampleTests/Update/UpdateTests.cs
+++ b/test/OperationsExampleTests/Update/UpdateTests.cs
@@ -10,67 +10,65 @@
 
 namespace OperationsExampleTests.Update
 {
-    [Collection("WebHostCollection")]
-    public class UpdateTests
+    public class UpdateTests : Fixture
     {
-        private readonly Fixture _fixture;
         private readonly Faker _faker = new Faker();
 
-        public UpdateTests(Fixture fixture)
-        {
-            _fixture = fixture;
-        }
-
         [Fact]
-        public async Task Can_Update_Article()
+        public async Task Can_Update_Author()
         {
             // arrange
-            var context = _fixture.GetService<AppDbContext>();
-            var article = ArticleFactory.Get();
-            var updates = ArticleFactory.Get();
-            context.Articles.Add(article);
+            var context = GetService<AppDbContext>();
+            var author = AuthorFactory.Get();
+            var updates = AuthorFactory.Get();
+            context.Authors.Add(author);
             context.SaveChanges();
 
             var content = new
             {
                 operations = new[] {
-                    new {
-                        op = "replace",
-                        data = new {
-                            type = "articles",
-                            id = article.Id,
-                            attributes = new {
+                    new Dictionary<string, object> {
+                        { "op", "update" },
+                        { "ref", new {
+                            type = "authors",
+                            id = author.Id,
+                        } },
+                        { "data", new {
+                            type = "authors",
+                            id = author.Id,
+                            attributes = new
+                            {
                                 name = updates.Name
                             }
-                        }
-                    },
+                        } },
+                    }
                 }
             };
 
             // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(result.response);
-            Assert.NotNull(result.data);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(1, result.data.Operations.Count);
+            Assert.NotNull(response);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.NotNull(data);
+            Assert.Equal(1, data.Operations.Count);
 
-            var attrs = result.data.Operations.Single().DataObject.Attributes;
+            var attrs = data.Operations.Single().DataObject.Attributes;
             Assert.Equal(updates.Name, attrs["name"]);
         }
 
         [Fact]
-        public async Task Can_Update_Articles()
+        public async Task Can_Update_Authors()
         {
             // arrange
             var count = _faker.Random.Int(1, 10);
-            var context = _fixture.GetService<AppDbContext>();
+            var context = GetService<AppDbContext>();
 
-            var articles = ArticleFactory.Get(count);
-            var updates = ArticleFactory.Get(count);
+            var authors = AuthorFactory.Get(count);
+            var updates = AuthorFactory.Get(count);
 
-            context.Articles.AddRange(articles);
+            context.Authors.AddRange(authors);
             context.SaveChanges();
 
             var content = new
@@ -79,32 +77,34 @@ public async Task Can_Update_Articles()
             };
 
             for (int i = 0; i < count; i++)
-                content.operations.Add(new
-                {
-                    op = "replace",
-                    data = new
-                    {
-                        type = "articles",
-                        id = articles[i].Id,
+                content.operations.Add(new Dictionary<string, object> {
+                    { "op", "update" },
+                    { "ref", new {
+                        type = "authors",
+                        id = authors[i].Id,
+                    } },
+                    { "data", new {
+                        type = "authors",
+                        id = authors[i].Id,
                         attributes = new
                         {
                             name = updates[i].Name
                         }
-                    }
+                    } },
                 });
 
             // act
-            var result = await _fixture.PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(result.response);
-            Assert.NotNull(result.data);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(count, result.data.Operations.Count);
+            Assert.NotNull(response);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.NotNull(data);
+            Assert.Equal(count, data.Operations.Count);
 
             for (int i = 0; i < count; i++)
             {
-                var attrs = result.data.Operations[i].DataObject.Attributes;
+                var attrs = data.Operations[i].DataObject.Attributes;
                 Assert.Equal(updates[i].Name, attrs["name"]);
             }
         }
diff --git a/test/UnitTests/TestScopedServiceProvider.cs b/test/UnitTests/TestScopedServiceProvider.cs
new file mode 100644
index 0000000000..af68e340b9
--- /dev/null
+++ b/test/UnitTests/TestScopedServiceProvider.cs
@@ -0,0 +1,28 @@
+using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Http;
+using Moq;
+using System;
+
+namespace UnitTests
+{
+    public class TestScopedServiceProvider : IScopedServiceProvider
+    {
+        private readonly IServiceProvider _serviceProvider;
+        private Mock<IHttpContextAccessor> _httpContextAccessorMock = new Mock<IHttpContextAccessor>();
+
+        public TestScopedServiceProvider(IServiceProvider serviceProvider)
+        {
+            _serviceProvider = serviceProvider;
+        }
+
+        public object GetService(Type serviceType)
+        {
+            if (serviceType == typeof(IHttpContextAccessor))
+            {
+                return _httpContextAccessorMock.Object;
+            }
+
+            return _serviceProvider.GetService(serviceType);
+        }
+    }
+}

From d3c9269f479b61707a08dce17ce36d1b3c437453 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 27 Mar 2018 07:35:03 -0500
Subject: [PATCH 107/227] move operations AppDbContext into the shared
 JsonDotNetCoreExample project

having a single db  makes CI easier to configure
---
 .../Data/AppDbContext.cs                      |   9 +-
 .../20170315140127_initial.Designer.cs        |  92 ---------------
 ...330020650_AddAssignedTodoItems.Designer.cs | 100 ----------------
 .../20170330020650_AddAssignedTodoItems.cs    |  43 -------
 ...20170330234539_AddGuidProperty.Designer.cs | 102 -----------------
 .../20170330234539_AddGuidProperty.cs         |  24 ----
 ...950_AddCreatesAndAchievedDates.Designer.cs | 108 ------------------
 ...170424180950_AddCreatesAndAchievedDates.cs |  33 ------
 .../20170426232509_AddCamelCasedModel.cs      |  30 -----
 ....cs => 20180327120810_initial.Designer.cs} |  51 ++++++++-
 ...7_initial.cs => 20180327120810_initial.cs} |  90 +++++++++++++--
 .../Migrations/AppDbContextModelSnapshot.cs   |  48 +++++++-
 .../Models/Article.cs                         |  20 ++--
 .../Models/Author.cs                          |   2 +-
 .../JsonApiDotNetCoreExample/Program.cs       |   5 +-
 .../JsonApiDotNetCoreExample/appsettings.json |  21 ++--
 .../OperationsExample/Data/AppDbContext.cs    |  15 ---
 ...80325130426_ArticlesAndAuthors.Designer.cs |  61 ----------
 .../20180325130426_ArticlesAndAuthors.cs      |  60 ----------
 .../Migrations/AppDbContextModelSnapshot.cs   |  60 ----------
 .../OperationsExample.csproj                  |   1 +
 src/Examples/OperationsExample/Startup.cs     |   3 +-
 .../OperationsExample/appsettings.json        |   2 +-
 .../appsettings.json                          |  21 ++--
 test/NoEntityFrameworkTests/appsettings.json  |  21 ++--
 test/OperationsExampleTests/Add/AddTests.cs   |   2 +-
 .../Factories/ArticleFactory.cs               |   4 +-
 .../Factories/AuthorFactory.cs                |   2 +-
 test/OperationsExampleTests/Fixture.cs        |   2 +-
 test/OperationsExampleTests/Get/GetTests.cs   |   2 +-
 .../Remove/RemoveTests.cs                     |   2 +-
 test/OperationsExampleTests/TestStartup.cs    |   2 +-
 .../Transactions/TransactionFailureTests.cs   |   2 +-
 .../Update/UpdateTests.cs                     |   2 +-
 test/OperationsExampleTests/appsettings.json  |  22 ++--
 35 files changed, 246 insertions(+), 818 deletions(-)
 delete mode 100644 src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.Designer.cs
 delete mode 100755 src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.Designer.cs
 delete mode 100755 src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.cs
 delete mode 100755 src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.Designer.cs
 delete mode 100755 src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.cs
 delete mode 100755 src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.Designer.cs
 delete mode 100755 src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.cs
 delete mode 100755 src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.cs
 rename src/Examples/JsonApiDotNetCoreExample/Migrations/{20170426232509_AddCamelCasedModel.Designer.cs => 20180327120810_initial.Designer.cs} (72%)
 mode change 100755 => 100644
 rename src/Examples/JsonApiDotNetCoreExample/Migrations/{20170315140127_initial.cs => 20180327120810_initial.cs} (54%)
 rename src/Examples/{OperationsExample => JsonApiDotNetCoreExample}/Models/Article.cs (85%)
 rename src/Examples/{OperationsExample => JsonApiDotNetCoreExample}/Models/Author.cs (86%)
 delete mode 100644 src/Examples/OperationsExample/Data/AppDbContext.cs
 delete mode 100644 src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.Designer.cs
 delete mode 100644 src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.cs
 delete mode 100755 src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs

diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
index ccdf8e8d9f..4266ca9741 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
@@ -1,4 +1,4 @@
-using JsonApiDotNetCoreExample.Models;
+using JsonApiDotNetCoreExample.Models;
 using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
 
@@ -14,12 +14,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
         {
             modelBuilder.Entity<TodoItem>()
                 .Property(t => t.CreatedDate).HasDefaultValueSql("CURRENT_TIMESTAMP").IsRequired();
-            
+
             modelBuilder.Entity<TodoItem>()
                 .HasOne(t => t.Assignee)
                 .WithMany(p => p.AssignedTodoItems)
                 .HasForeignKey(t => t.AssigneeId);
-            
+
             modelBuilder.Entity<TodoItem>()
                 .HasOne(t => t.Owner)
                 .WithMany(p => p.TodoItems)
@@ -34,5 +34,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
 
         [Resource("camelCasedModels")]
         public DbSet<CamelCasedModel> CamelCasedModels { get; set; }
+
+        public DbSet<Article> Articles { get; set; }
+        public DbSet<Author> Authors { get; set; }
     }
 }
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.Designer.cs
deleted file mode 100644
index be31f0ccae..0000000000
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.Designer.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using JsonApiDotNetCoreExample.Data;
-
-namespace JsonApiDotNetCoreExample.Migrations
-{
-    [DbContext(typeof(AppDbContext))]
-    [Migration("20170315140127_initial")]
-    partial class initial
-    {
-        protected override void BuildTargetModel(ModelBuilder modelBuilder)
-        {
-            modelBuilder
-                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "1.1.1");
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Person", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("FirstName");
-
-                    b.Property<string>("LastName");
-
-                    b.HasKey("Id");
-
-                    b.ToTable("People");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<Guid?>("CollectionId");
-
-                    b.Property<string>("Description");
-
-                    b.Property<long>("Ordinal");
-
-                    b.Property<int?>("OwnerId");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("CollectionId");
-
-                    b.HasIndex("OwnerId");
-
-                    b.ToTable("TodoItems");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b =>
-                {
-                    b.Property<Guid>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("Name");
-
-                    b.Property<int>("OwnerId");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("OwnerId");
-
-                    b.ToTable("TodoItemCollections");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
-                {
-                    b.HasOne("JsonApiDotNetCoreExample.Models.TodoItemCollection", "Collection")
-                        .WithMany("TodoItems")
-                        .HasForeignKey("CollectionId");
-
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner")
-                        .WithMany("TodoItems")
-                        .HasForeignKey("OwnerId");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b =>
-                {
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner")
-                        .WithMany("TodoItemCollections")
-                        .HasForeignKey("OwnerId")
-                        .OnDelete(DeleteBehavior.Cascade);
-                });
-        }
-    }
-}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.Designer.cs
deleted file mode 100755
index 52b60adbcb..0000000000
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.Designer.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using JsonApiDotNetCoreExample.Data;
-
-namespace JsonApiDotNetCoreExample.Migrations
-{
-    [DbContext(typeof(AppDbContext))]
-    [Migration("20170330020650_AddAssignedTodoItems")]
-    partial class AddAssignedTodoItems
-    {
-        protected override void BuildTargetModel(ModelBuilder modelBuilder)
-        {
-            modelBuilder
-                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "1.1.1");
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Person", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("FirstName");
-
-                    b.Property<string>("LastName");
-
-                    b.HasKey("Id");
-
-                    b.ToTable("People");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<int?>("AssigneeId");
-
-                    b.Property<Guid?>("CollectionId");
-
-                    b.Property<string>("Description");
-
-                    b.Property<long>("Ordinal");
-
-                    b.Property<int?>("OwnerId");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("AssigneeId");
-
-                    b.HasIndex("CollectionId");
-
-                    b.HasIndex("OwnerId");
-
-                    b.ToTable("TodoItems");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b =>
-                {
-                    b.Property<Guid>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("Name");
-
-                    b.Property<int>("OwnerId");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("OwnerId");
-
-                    b.ToTable("TodoItemCollections");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
-                {
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee")
-                        .WithMany("AssignedTodoItems")
-                        .HasForeignKey("AssigneeId");
-
-                    b.HasOne("JsonApiDotNetCoreExample.Models.TodoItemCollection", "Collection")
-                        .WithMany("TodoItems")
-                        .HasForeignKey("CollectionId");
-
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner")
-                        .WithMany("TodoItems")
-                        .HasForeignKey("OwnerId");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b =>
-                {
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner")
-                        .WithMany("TodoItemCollections")
-                        .HasForeignKey("OwnerId")
-                        .OnDelete(DeleteBehavior.Cascade);
-                });
-        }
-    }
-}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.cs
deleted file mode 100755
index 8a1810a9d8..0000000000
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-namespace JsonApiDotNetCoreExample.Migrations
-{
-    public partial class AddAssignedTodoItems : Migration
-    {
-        protected override void Up(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.AddColumn<int>(
-                name: "AssigneeId",
-                table: "TodoItems",
-                nullable: true);
-
-            migrationBuilder.CreateIndex(
-                name: "IX_TodoItems_AssigneeId",
-                table: "TodoItems",
-                column: "AssigneeId");
-
-            migrationBuilder.AddForeignKey(
-                name: "FK_TodoItems_People_AssigneeId",
-                table: "TodoItems",
-                column: "AssigneeId",
-                principalTable: "People",
-                principalColumn: "Id",
-                onDelete: ReferentialAction.Restrict);
-        }
-
-        protected override void Down(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.DropForeignKey(
-                name: "FK_TodoItems_People_AssigneeId",
-                table: "TodoItems");
-
-            migrationBuilder.DropIndex(
-                name: "IX_TodoItems_AssigneeId",
-                table: "TodoItems");
-
-            migrationBuilder.DropColumn(
-                name: "AssigneeId",
-                table: "TodoItems");
-        }
-    }
-}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.Designer.cs
deleted file mode 100755
index ded5d1b160..0000000000
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.Designer.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using JsonApiDotNetCoreExample.Data;
-
-namespace JsonApiDotNetCoreExample.Migrations
-{
-    [DbContext(typeof(AppDbContext))]
-    [Migration("20170330234539_AddGuidProperty")]
-    partial class AddGuidProperty
-    {
-        protected override void BuildTargetModel(ModelBuilder modelBuilder)
-        {
-            modelBuilder
-                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "1.1.1");
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Person", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("FirstName");
-
-                    b.Property<string>("LastName");
-
-                    b.HasKey("Id");
-
-                    b.ToTable("People");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<int?>("AssigneeId");
-
-                    b.Property<Guid?>("CollectionId");
-
-                    b.Property<string>("Description");
-
-                    b.Property<Guid>("GuidProperty");
-
-                    b.Property<long>("Ordinal");
-
-                    b.Property<int?>("OwnerId");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("AssigneeId");
-
-                    b.HasIndex("CollectionId");
-
-                    b.HasIndex("OwnerId");
-
-                    b.ToTable("TodoItems");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b =>
-                {
-                    b.Property<Guid>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("Name");
-
-                    b.Property<int>("OwnerId");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("OwnerId");
-
-                    b.ToTable("TodoItemCollections");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
-                {
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee")
-                        .WithMany("AssignedTodoItems")
-                        .HasForeignKey("AssigneeId");
-
-                    b.HasOne("JsonApiDotNetCoreExample.Models.TodoItemCollection", "Collection")
-                        .WithMany("TodoItems")
-                        .HasForeignKey("CollectionId");
-
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner")
-                        .WithMany("TodoItems")
-                        .HasForeignKey("OwnerId");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b =>
-                {
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner")
-                        .WithMany("TodoItemCollections")
-                        .HasForeignKey("OwnerId")
-                        .OnDelete(DeleteBehavior.Cascade);
-                });
-        }
-    }
-}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.cs
deleted file mode 100755
index 27815ce504..0000000000
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-namespace JsonApiDotNetCoreExample.Migrations
-{
-    public partial class AddGuidProperty : Migration
-    {
-        protected override void Up(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.AddColumn<Guid>(
-                name: "GuidProperty",
-                table: "TodoItems",
-                nullable: false,
-                defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
-        }
-
-        protected override void Down(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.DropColumn(
-                name: "GuidProperty",
-                table: "TodoItems");
-        }
-    }
-}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.Designer.cs
deleted file mode 100755
index 537b3b043a..0000000000
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.Designer.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using JsonApiDotNetCoreExample.Data;
-
-namespace JsonApiDotNetCoreExample.Migrations
-{
-    [DbContext(typeof(AppDbContext))]
-    [Migration("20170424180950_AddCreatesAndAchievedDates")]
-    partial class AddCreatesAndAchievedDates
-    {
-        protected override void BuildTargetModel(ModelBuilder modelBuilder)
-        {
-            modelBuilder
-                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "1.1.1");
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Person", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("FirstName");
-
-                    b.Property<string>("LastName");
-
-                    b.HasKey("Id");
-
-                    b.ToTable("People");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<DateTime?>("AchievedDate");
-
-                    b.Property<int?>("AssigneeId");
-
-                    b.Property<Guid?>("CollectionId");
-
-                    b.Property<DateTime>("CreatedDate")
-                        .ValueGeneratedOnAdd()
-                        .HasDefaultValueSql("CURRENT_TIMESTAMP");
-
-                    b.Property<string>("Description");
-
-                    b.Property<Guid>("GuidProperty");
-
-                    b.Property<long>("Ordinal");
-
-                    b.Property<int?>("OwnerId");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("AssigneeId");
-
-                    b.HasIndex("CollectionId");
-
-                    b.HasIndex("OwnerId");
-
-                    b.ToTable("TodoItems");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b =>
-                {
-                    b.Property<Guid>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("Name");
-
-                    b.Property<int>("OwnerId");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("OwnerId");
-
-                    b.ToTable("TodoItemCollections");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
-                {
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee")
-                        .WithMany("AssignedTodoItems")
-                        .HasForeignKey("AssigneeId");
-
-                    b.HasOne("JsonApiDotNetCoreExample.Models.TodoItemCollection", "Collection")
-                        .WithMany("TodoItems")
-                        .HasForeignKey("CollectionId");
-
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner")
-                        .WithMany("TodoItems")
-                        .HasForeignKey("OwnerId");
-                });
-
-            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b =>
-                {
-                    b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner")
-                        .WithMany("TodoItemCollections")
-                        .HasForeignKey("OwnerId")
-                        .OnDelete(DeleteBehavior.Cascade);
-                });
-        }
-    }
-}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.cs
deleted file mode 100755
index 1c36034fe3..0000000000
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-namespace JsonApiDotNetCoreExample.Migrations
-{
-    public partial class AddCreatesAndAchievedDates : Migration
-    {
-        protected override void Up(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.AddColumn<DateTime>(
-                name: "AchievedDate",
-                table: "TodoItems",
-                nullable: true);
-
-            migrationBuilder.AddColumn<DateTime>(
-                name: "CreatedDate",
-                table: "TodoItems",
-                nullable: false,
-                defaultValueSql: "CURRENT_TIMESTAMP");
-        }
-
-        protected override void Down(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.DropColumn(
-                name: "AchievedDate",
-                table: "TodoItems");
-
-            migrationBuilder.DropColumn(
-                name: "CreatedDate",
-                table: "TodoItems");
-        }
-    }
-}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.cs
deleted file mode 100755
index fbec5e0a79..0000000000
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Metadata;
-
-namespace JsonApiDotNetCoreExample.Migrations
-{
-    public partial class AddCamelCasedModel : Migration
-    {
-        protected override void Up(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.CreateTable(
-                name: "CamelCasedModels",
-                columns: table => new
-                {
-                    Id = table.Column<int>(nullable: false)
-                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
-                    CompoundAttr = table.Column<string>(nullable: true)
-                },
-                constraints: table =>
-                {
-                    table.PrimaryKey("PK_CamelCasedModels", x => x.Id);
-                });
-        }
-
-        protected override void Down(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.DropTable(
-                name: "CamelCasedModels");
-        }
-    }
-}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs
old mode 100755
new mode 100644
similarity index 72%
rename from src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.Designer.cs
rename to src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs
index e43d2afc1f..c86425b00c
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.Designer.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs
@@ -1,21 +1,53 @@
-using System;
+// <auto-generated />
+using JsonApiDotNetCoreExample.Data;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.Infrastructure;
 using Microsoft.EntityFrameworkCore.Metadata;
 using Microsoft.EntityFrameworkCore.Migrations;
-using JsonApiDotNetCoreExample.Data;
+using Microsoft.EntityFrameworkCore.Storage;
+using Microsoft.EntityFrameworkCore.Storage.Internal;
+using System;
 
 namespace JsonApiDotNetCoreExample.Migrations
 {
     [DbContext(typeof(AppDbContext))]
-    [Migration("20170426232509_AddCamelCasedModel")]
-    partial class AddCamelCasedModel
+    [Migration("20180327120810_initial")]
+    partial class initial
     {
         protected override void BuildTargetModel(ModelBuilder modelBuilder)
         {
+#pragma warning disable 612, 618
             modelBuilder
                 .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "1.1.1");
+                .HasAnnotation("ProductVersion", "2.0.1-rtm-125");
+
+            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Article", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<int>("AuthorId");
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("AuthorId");
+
+                    b.ToTable("Articles");
+                });
+
+            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Author", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Authors");
+                });
 
             modelBuilder.Entity("JsonApiDotNetCoreExample.Models.CamelCasedModel", b =>
                 {
@@ -93,6 +125,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder)
                     b.ToTable("TodoItemCollections");
                 });
 
+            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Article", b =>
+                {
+                    b.HasOne("JsonApiDotNetCoreExample.Models.Author", "Author")
+                        .WithMany("Articles")
+                        .HasForeignKey("AuthorId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
             modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
                 {
                     b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee")
@@ -115,6 +155,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder)
                         .HasForeignKey("OwnerId")
                         .OnDelete(DeleteBehavior.Cascade);
                 });
+#pragma warning restore 612, 618
         }
     }
 }
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
similarity index 54%
rename from src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.cs
rename to src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
index e0b4e3b40b..ba19b62ef6 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
@@ -1,6 +1,7 @@
-using System;
+using Microsoft.EntityFrameworkCore.Metadata;
 using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Metadata;
+using System;
+using System.Collections.Generic;
 
 namespace JsonApiDotNetCoreExample.Migrations
 {
@@ -8,6 +9,32 @@ public partial class initial : Migration
     {
         protected override void Up(MigrationBuilder migrationBuilder)
         {
+            migrationBuilder.CreateTable(
+                name: "Authors",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
+                    Name = table.Column<string>(nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Authors", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "CamelCasedModels",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
+                    CompoundAttr = table.Column<string>(nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_CamelCasedModels", x => x.Id);
+                });
+
             migrationBuilder.CreateTable(
                 name: "People",
                 columns: table => new
@@ -22,6 +49,26 @@ protected override void Up(MigrationBuilder migrationBuilder)
                     table.PrimaryKey("PK_People", x => x.Id);
                 });
 
+            migrationBuilder.CreateTable(
+                name: "Articles",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
+                    AuthorId = table.Column<int>(nullable: false),
+                    Name = table.Column<string>(nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Articles", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Articles_Authors_AuthorId",
+                        column: x => x.AuthorId,
+                        principalTable: "Authors",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
             migrationBuilder.CreateTable(
                 name: "TodoItemCollections",
                 columns: table => new
@@ -47,14 +94,24 @@ protected override void Up(MigrationBuilder migrationBuilder)
                 {
                     Id = table.Column<int>(nullable: false)
                         .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
+                    AchievedDate = table.Column<DateTime>(nullable: true),
+                    AssigneeId = table.Column<int>(nullable: true),
                     CollectionId = table.Column<Guid>(nullable: true),
+                    CreatedDate = table.Column<DateTime>(nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"),
                     Description = table.Column<string>(nullable: true),
+                    GuidProperty = table.Column<Guid>(nullable: false),
                     Ordinal = table.Column<long>(nullable: false),
                     OwnerId = table.Column<int>(nullable: true)
                 },
                 constraints: table =>
                 {
                     table.PrimaryKey("PK_TodoItems", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_TodoItems_People_AssigneeId",
+                        column: x => x.AssigneeId,
+                        principalTable: "People",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
                     table.ForeignKey(
                         name: "FK_TodoItems_TodoItemCollections_CollectionId",
                         column: x => x.CollectionId,
@@ -69,6 +126,21 @@ protected override void Up(MigrationBuilder migrationBuilder)
                         onDelete: ReferentialAction.Restrict);
                 });
 
+            migrationBuilder.CreateIndex(
+                name: "IX_Articles_AuthorId",
+                table: "Articles",
+                column: "AuthorId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_TodoItemCollections_OwnerId",
+                table: "TodoItemCollections",
+                column: "OwnerId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_TodoItems_AssigneeId",
+                table: "TodoItems",
+                column: "AssigneeId");
+
             migrationBuilder.CreateIndex(
                 name: "IX_TodoItems_CollectionId",
                 table: "TodoItems",
@@ -78,18 +150,22 @@ protected override void Up(MigrationBuilder migrationBuilder)
                 name: "IX_TodoItems_OwnerId",
                 table: "TodoItems",
                 column: "OwnerId");
-
-            migrationBuilder.CreateIndex(
-                name: "IX_TodoItemCollections_OwnerId",
-                table: "TodoItemCollections",
-                column: "OwnerId");
         }
 
         protected override void Down(MigrationBuilder migrationBuilder)
         {
+            migrationBuilder.DropTable(
+                name: "Articles");
+
+            migrationBuilder.DropTable(
+                name: "CamelCasedModels");
+
             migrationBuilder.DropTable(
                 name: "TodoItems");
 
+            migrationBuilder.DropTable(
+                name: "Authors");
+
             migrationBuilder.DropTable(
                 name: "TodoItemCollections");
 
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs
index 5de99f5078..c0794103fe 100755
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs
@@ -1,8 +1,12 @@
-using System;
+// <auto-generated />
+using JsonApiDotNetCoreExample.Data;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.Infrastructure;
 using Microsoft.EntityFrameworkCore.Metadata;
-using JsonApiDotNetCoreExample.Data;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage;
+using Microsoft.EntityFrameworkCore.Storage.Internal;
+using System;
 
 namespace JsonApiDotNetCoreExample.Migrations
 {
@@ -11,9 +15,38 @@ partial class AppDbContextModelSnapshot : ModelSnapshot
     {
         protected override void BuildModel(ModelBuilder modelBuilder)
         {
+#pragma warning disable 612, 618
             modelBuilder
                 .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "1.1.1");
+                .HasAnnotation("ProductVersion", "2.0.1-rtm-125");
+
+            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Article", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<int>("AuthorId");
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("AuthorId");
+
+                    b.ToTable("Articles");
+                });
+
+            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Author", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd();
+
+                    b.Property<string>("Name");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Authors");
+                });
 
             modelBuilder.Entity("JsonApiDotNetCoreExample.Models.CamelCasedModel", b =>
                 {
@@ -91,6 +124,14 @@ protected override void BuildModel(ModelBuilder modelBuilder)
                     b.ToTable("TodoItemCollections");
                 });
 
+            modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Article", b =>
+                {
+                    b.HasOne("JsonApiDotNetCoreExample.Models.Author", "Author")
+                        .WithMany("Articles")
+                        .HasForeignKey("AuthorId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
             modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b =>
                 {
                     b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee")
@@ -113,6 +154,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
                         .HasForeignKey("OwnerId")
                         .OnDelete(DeleteBehavior.Cascade);
                 });
+#pragma warning restore 612, 618
         }
     }
 }
diff --git a/src/Examples/OperationsExample/Models/Article.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs
similarity index 85%
rename from src/Examples/OperationsExample/Models/Article.cs
rename to src/Examples/JsonApiDotNetCoreExample/Models/Article.cs
index 4353c02ee2..c633d58bdd 100644
--- a/src/Examples/OperationsExample/Models/Article.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs
@@ -1,14 +1,14 @@
-using JsonApiDotNetCore.Models;
-
-namespace OperationsExample.Models
-{
-    public class Article : Identifiable
-    {
-        [Attr("name")]
+using JsonApiDotNetCore.Models;
+
+namespace JsonApiDotNetCoreExample.Models
+{
+    public class Article : Identifiable
+    {
+        [Attr("name")]
         public string Name { get; set; }
 
         [HasOne("author")]
         public Author Author { get; set; }
-        public int AuthorId { get; set; }
-    }
-}
+        public int AuthorId { get; set; }
+    }
+}
diff --git a/src/Examples/OperationsExample/Models/Author.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs
similarity index 86%
rename from src/Examples/OperationsExample/Models/Author.cs
rename to src/Examples/JsonApiDotNetCoreExample/Models/Author.cs
index 7d6039480a..c77ad007c8 100644
--- a/src/Examples/OperationsExample/Models/Author.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs
@@ -1,7 +1,7 @@
 using JsonApiDotNetCore.Models;
 using System.Collections.Generic;
 
-namespace OperationsExample.Models
+namespace JsonApiDotNetCoreExample.Models
 {
     public class Author : Identifiable
     {
diff --git a/src/Examples/JsonApiDotNetCoreExample/Program.cs b/src/Examples/JsonApiDotNetCoreExample/Program.cs
index e4e3fe355e..b9bbe37b6a 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Program.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Program.cs
@@ -5,10 +5,7 @@ namespace JsonApiDotNetCoreExample
 {
     public class Program
     {
-        public static void Main(string[] args)
-        {
-            BuildWebHost(args).Run();
-        }
+        public static void Main(string[] args) => BuildWebHost(args).Run();
 
         public static IWebHost BuildWebHost(string[] args) =>
             WebHost.CreateDefaultBuilder(args)
diff --git a/src/Examples/JsonApiDotNetCoreExample/appsettings.json b/src/Examples/JsonApiDotNetCoreExample/appsettings.json
index ceb4a1ed73..578225ef14 100755
--- a/src/Examples/JsonApiDotNetCoreExample/appsettings.json
+++ b/src/Examples/JsonApiDotNetCoreExample/appsettings.json
@@ -1,14 +1,13 @@
 {
-  "Data": {
-    "DefaultConnection":
-      "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=password"
-  },
-  "Logging": {
-    "IncludeScopes": false,
-    "LogLevel": {
-      "Default": "Trace",
-      "System": "Trace",
-      "Microsoft": "Trace"
+    "Data": {
+        "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
+    },
+    "Logging": {
+        "IncludeScopes": false,
+        "LogLevel": {
+            "Default": "Trace",
+            "System": "Trace",
+            "Microsoft": "Trace"
+        }
     }
-  }
 }
diff --git a/src/Examples/OperationsExample/Data/AppDbContext.cs b/src/Examples/OperationsExample/Data/AppDbContext.cs
deleted file mode 100644
index 3d5b3e2e54..0000000000
--- a/src/Examples/OperationsExample/Data/AppDbContext.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using OperationsExample.Models;
-
-namespace OperationsExample.Data
-{
-    public class AppDbContext : DbContext
-    {
-        public AppDbContext(DbContextOptions<AppDbContext> options)
-        : base(options)
-        { }
-
-        public DbSet<Article> Articles { get; set; }
-        public DbSet<Author> Authors { get; set; }
-    }
-}
diff --git a/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.Designer.cs b/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.Designer.cs
deleted file mode 100644
index e9934cb776..0000000000
--- a/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.Designer.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-// <auto-generated />
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage;
-using Microsoft.EntityFrameworkCore.Storage.Internal;
-using OperationsExample.Data;
-using System;
-
-namespace OperationsExample.Migrations
-{
-    [DbContext(typeof(AppDbContext))]
-    [Migration("20180325130426_ArticlesAndAuthors")]
-    partial class ArticlesAndAuthors
-    {
-        protected override void BuildTargetModel(ModelBuilder modelBuilder)
-        {
-#pragma warning disable 612, 618
-            modelBuilder
-                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "2.0.1-rtm-125");
-
-            modelBuilder.Entity("OperationsExample.Models.Article", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<int?>("AuthorId");
-
-                    b.Property<string>("Name");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("AuthorId");
-
-                    b.ToTable("Articles");
-                });
-
-            modelBuilder.Entity("OperationsExample.Models.Author", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("Name");
-
-                    b.HasKey("Id");
-
-                    b.ToTable("Authors");
-                });
-
-            modelBuilder.Entity("OperationsExample.Models.Article", b =>
-                {
-                    b.HasOne("OperationsExample.Models.Author", "Author")
-                        .WithMany("Articles")
-                        .HasForeignKey("AuthorId");
-                });
-#pragma warning restore 612, 618
-        }
-    }
-}
diff --git a/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.cs b/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.cs
deleted file mode 100644
index 1a0d5e309a..0000000000
--- a/src/Examples/OperationsExample/Migrations/20180325130426_ArticlesAndAuthors.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using System;
-using System.Collections.Generic;
-
-namespace OperationsExample.Migrations
-{
-    public partial class ArticlesAndAuthors : Migration
-    {
-        protected override void Up(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.CreateTable(
-                name: "Authors",
-                columns: table => new
-                {
-                    Id = table.Column<int>(nullable: false)
-                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
-                    Name = table.Column<string>(nullable: true)
-                },
-                constraints: table =>
-                {
-                    table.PrimaryKey("PK_Authors", x => x.Id);
-                });
-
-            migrationBuilder.CreateTable(
-                name: "Articles",
-                columns: table => new
-                {
-                    Id = table.Column<int>(nullable: false)
-                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
-                    AuthorId = table.Column<int>(nullable: true),
-                    Name = table.Column<string>(nullable: true)
-                },
-                constraints: table =>
-                {
-                    table.PrimaryKey("PK_Articles", x => x.Id);
-                    table.ForeignKey(
-                        name: "FK_Articles_Authors_AuthorId",
-                        column: x => x.AuthorId,
-                        principalTable: "Authors",
-                        principalColumn: "Id",
-                        onDelete: ReferentialAction.Restrict);
-                });
-
-            migrationBuilder.CreateIndex(
-                name: "IX_Articles_AuthorId",
-                table: "Articles",
-                column: "AuthorId");
-        }
-
-        protected override void Down(MigrationBuilder migrationBuilder)
-        {
-            migrationBuilder.DropTable(
-                name: "Articles");
-
-            migrationBuilder.DropTable(
-                name: "Authors");
-        }
-    }
-}
diff --git a/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs b/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs
deleted file mode 100755
index b4c9a0ebba..0000000000
--- a/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// <auto-generated />
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage;
-using Microsoft.EntityFrameworkCore.Storage.Internal;
-using OperationsExample.Data;
-using System;
-
-namespace OperationsExample.Migrations
-{
-    [DbContext(typeof(AppDbContext))]
-    partial class AppDbContextModelSnapshot : ModelSnapshot
-    {
-        protected override void BuildModel(ModelBuilder modelBuilder)
-        {
-#pragma warning disable 612, 618
-            modelBuilder
-                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
-                .HasAnnotation("ProductVersion", "2.0.1-rtm-125");
-
-            modelBuilder.Entity("OperationsExample.Models.Article", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<int?>("AuthorId");
-
-                    b.Property<string>("Name");
-
-                    b.HasKey("Id");
-
-                    b.HasIndex("AuthorId");
-
-                    b.ToTable("Articles");
-                });
-
-            modelBuilder.Entity("OperationsExample.Models.Author", b =>
-                {
-                    b.Property<int>("Id")
-                        .ValueGeneratedOnAdd();
-
-                    b.Property<string>("Name");
-
-                    b.HasKey("Id");
-
-                    b.ToTable("Authors");
-                });
-
-            modelBuilder.Entity("OperationsExample.Models.Article", b =>
-                {
-                    b.HasOne("OperationsExample.Models.Author", "Author")
-                        .WithMany("Articles")
-                        .HasForeignKey("AuthorId");
-                });
-#pragma warning restore 612, 618
-        }
-    }
-}
diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj
index ebbdc91fc1..69ad5653ce 100644
--- a/src/Examples/OperationsExample/OperationsExample.csproj
+++ b/src/Examples/OperationsExample/OperationsExample.csproj
@@ -8,6 +8,7 @@
 
   <ItemGroup>
     <ProjectReference Include="../../JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
+    <ProjectReference Include="..\JsonApiDotNetCoreExample\JsonApiDotNetCoreExample.csproj" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/src/Examples/OperationsExample/Startup.cs b/src/Examples/OperationsExample/Startup.cs
index 78a6d29f69..c11a3e9d26 100644
--- a/src/Examples/OperationsExample/Startup.cs
+++ b/src/Examples/OperationsExample/Startup.cs
@@ -1,13 +1,12 @@
 using System;
 using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCoreExample.Data;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
-using OperationsExample.Data;
-
 
 namespace OperationsExample
 {
diff --git a/src/Examples/OperationsExample/appsettings.json b/src/Examples/OperationsExample/appsettings.json
index 2bcbebd13a..0d77cd40f2 100644
--- a/src/Examples/OperationsExample/appsettings.json
+++ b/src/Examples/OperationsExample/appsettings.json
@@ -1,6 +1,6 @@
 {
     "Data": {
-        "DefaultConnection": "Host=localhost;Port=5432;Database=OperationsExample;User ID=postgres;Password=postgres"
+        "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
     },
     "Logging": {
         "IncludeScopes": false,
diff --git a/test/JsonApiDotNetCoreExampleTests/appsettings.json b/test/JsonApiDotNetCoreExampleTests/appsettings.json
index 7af3457293..e65cee8d0d 100644
--- a/test/JsonApiDotNetCoreExampleTests/appsettings.json
+++ b/test/JsonApiDotNetCoreExampleTests/appsettings.json
@@ -1,14 +1,13 @@
 {
-  "Data": {
-    "DefaultConnection":
-      "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password="
-  },
-  "Logging": {
-    "IncludeScopes": false,
-    "LogLevel": {
-      "Default": "Error",
-      "System": "Information",
-      "Microsoft": "Information"
+    "Data": {
+        "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
+    },
+    "Logging": {
+        "IncludeScopes": false,
+        "LogLevel": {
+            "Default": "Error",
+            "System": "Information",
+            "Microsoft": "Information"
+        }
     }
-  }
 }
diff --git a/test/NoEntityFrameworkTests/appsettings.json b/test/NoEntityFrameworkTests/appsettings.json
index 7067b2bee0..01f85e6699 100644
--- a/test/NoEntityFrameworkTests/appsettings.json
+++ b/test/NoEntityFrameworkTests/appsettings.json
@@ -1,14 +1,13 @@
 {
-  "Data": {
-    "DefaultConnection":
-      "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password="
-  },
-  "Logging": {
-    "IncludeScopes": false,
-    "LogLevel": {
-      "Default": "Debug",
-      "System": "Information",
-      "Microsoft": "Information"
+    "Data": {
+        "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
+    },
+    "Logging": {
+        "IncludeScopes": false,
+        "LogLevel": {
+            "Default": "Debug",
+            "System": "Information",
+            "Microsoft": "Information"
+        }
     }
-  }
 }
diff --git a/test/OperationsExampleTests/Add/AddTests.cs b/test/OperationsExampleTests/Add/AddTests.cs
index 2390973594..39e9e8a2a6 100644
--- a/test/OperationsExampleTests/Add/AddTests.cs
+++ b/test/OperationsExampleTests/Add/AddTests.cs
@@ -4,8 +4,8 @@
 using System.Threading.Tasks;
 using Bogus;
 using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCoreExample.Data;
 using Microsoft.EntityFrameworkCore;
-using OperationsExample.Data;
 using OperationsExampleTests.Factories;
 using Xunit;
 
diff --git a/test/OperationsExampleTests/Factories/ArticleFactory.cs b/test/OperationsExampleTests/Factories/ArticleFactory.cs
index 1907e2de24..a03bc3fbea 100644
--- a/test/OperationsExampleTests/Factories/ArticleFactory.cs
+++ b/test/OperationsExampleTests/Factories/ArticleFactory.cs
@@ -1,6 +1,6 @@
 using System.Collections.Generic;
 using Bogus;
-using OperationsExample.Models;
+using JsonApiDotNetCoreExample.Models;
 
 namespace OperationsExampleTests.Factories
 {
@@ -22,4 +22,4 @@ public static List<Article> Get(int count)
             return articles;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/test/OperationsExampleTests/Factories/AuthorFactory.cs b/test/OperationsExampleTests/Factories/AuthorFactory.cs
index 2afe914b54..e80b100a59 100644
--- a/test/OperationsExampleTests/Factories/AuthorFactory.cs
+++ b/test/OperationsExampleTests/Factories/AuthorFactory.cs
@@ -1,6 +1,6 @@
 using System.Collections.Generic;
 using Bogus;
-using OperationsExample.Models;
+using JsonApiDotNetCoreExample.Models;
 
 namespace OperationsExampleTests.Factories
 {
diff --git a/test/OperationsExampleTests/Fixture.cs b/test/OperationsExampleTests/Fixture.cs
index 5a594940af..11621d36e4 100644
--- a/test/OperationsExampleTests/Fixture.cs
+++ b/test/OperationsExampleTests/Fixture.cs
@@ -2,10 +2,10 @@
 using System.Net.Http;
 using System.Net.Http.Headers;
 using System.Threading.Tasks;
+using JsonApiDotNetCoreExample.Data;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.TestHost;
 using Newtonsoft.Json;
-using OperationsExample.Data;
 using Xunit;
 
 [assembly: CollectionBehavior(DisableTestParallelization = true)]
diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs
index efc06424ce..1bf0393fa8 100644
--- a/test/OperationsExampleTests/Get/GetTests.cs
+++ b/test/OperationsExampleTests/Get/GetTests.cs
@@ -5,7 +5,7 @@
 using System.Threading.Tasks;
 using Bogus;
 using JsonApiDotNetCore.Models.Operations;
-using OperationsExample.Data;
+using JsonApiDotNetCoreExample.Data;
 using OperationsExampleTests.Factories;
 using Xunit;
 
diff --git a/test/OperationsExampleTests/Remove/RemoveTests.cs b/test/OperationsExampleTests/Remove/RemoveTests.cs
index ae647f13b9..b5e0cffaf3 100644
--- a/test/OperationsExampleTests/Remove/RemoveTests.cs
+++ b/test/OperationsExampleTests/Remove/RemoveTests.cs
@@ -4,7 +4,7 @@
 using System.Threading.Tasks;
 using Bogus;
 using JsonApiDotNetCore.Models.Operations;
-using OperationsExample.Data;
+using JsonApiDotNetCoreExample.Data;
 using OperationsExampleTests.Factories;
 using Xunit;
 
diff --git a/test/OperationsExampleTests/TestStartup.cs b/test/OperationsExampleTests/TestStartup.cs
index 26ee1fdbc3..449c193177 100644
--- a/test/OperationsExampleTests/TestStartup.cs
+++ b/test/OperationsExampleTests/TestStartup.cs
@@ -1,9 +1,9 @@
 using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Services;
+using JsonApiDotNetCoreExample.Data;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.Extensions.DependencyInjection;
 using OperationsExample;
-using OperationsExample.Data;
 using System;
 using UnitTests;
 
diff --git a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
index 635b9b89e4..05dea7f29d 100644
--- a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
+++ b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
@@ -4,8 +4,8 @@
 using System.Threading.Tasks;
 using Bogus;
 using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCoreExample.Data;
 using Microsoft.EntityFrameworkCore;
-using OperationsExample.Data;
 using OperationsExampleTests.Factories;
 using Xunit;
 
diff --git a/test/OperationsExampleTests/Update/UpdateTests.cs b/test/OperationsExampleTests/Update/UpdateTests.cs
index 5538fa5830..c5d0f20900 100644
--- a/test/OperationsExampleTests/Update/UpdateTests.cs
+++ b/test/OperationsExampleTests/Update/UpdateTests.cs
@@ -1,6 +1,6 @@
 using Bogus;
 using JsonApiDotNetCore.Models.Operations;
-using OperationsExample.Data;
+using JsonApiDotNetCoreExample.Data;
 using OperationsExampleTests.Factories;
 using System.Collections.Generic;
 using System.Linq;
diff --git a/test/OperationsExampleTests/appsettings.json b/test/OperationsExampleTests/appsettings.json
index c1061281cc..0d77cd40f2 100644
--- a/test/OperationsExampleTests/appsettings.json
+++ b/test/OperationsExampleTests/appsettings.json
@@ -1,13 +1,13 @@
-{
-  "Data": {
-    "DefaultConnection": "Host=localhost;Port=5432;Database=OperationsExample;User ID=postgres;Password=password"
-  },
-  "Logging": {
-    "IncludeScopes": false,
-    "LogLevel": {
-      "Default": "Trace",
-      "System": "Trace",
-      "Microsoft": "Trace"
+{
+    "Data": {
+        "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
+    },
+    "Logging": {
+        "IncludeScopes": false,
+        "LogLevel": {
+            "Default": "Trace",
+            "System": "Trace",
+            "Microsoft": "Trace"
+        }
     }
-  }
 }

From 0884b649b269c1aa417f30881f0d28a63b265f6f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 27 Mar 2018 08:56:10 -0500
Subject: [PATCH 108/227] don't use docfx on non-windows platforms

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index c712227334..7b2c112414 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -13,11 +13,16 @@
     <RepositoryType>git</RepositoryType>
     <RepositoryUrl>https://github.com/json-api-dotnet/JsonApiDotNetCore</RepositoryUrl>
   </PropertyGroup>
+  <PropertyGroup>
+    <IsWindows Condition="'$(OS)' == 'Windows_NT'">true</IsWindows>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
     <DocumentationFile>bin\Release\netstandard2.0\JsonApiDotNetCore.xml</DocumentationFile>
   </PropertyGroup>
-  <ItemGroup>
+  <ItemGroup Condition="$(IsWindows)">
     <PackageReference Include="docfx.console" Version="2.33.0" />
+  </ItemGroup>
+  <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />

From 6808741fdf0f0a6768fc28769bd1255206f1d048 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 27 Mar 2018 09:03:36 -0500
Subject: [PATCH 109/227] fix(csproj): correct IsWindows condition check

---
 .../JsonApiDotNetCore.csproj                  | 21 +++++++++++--------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 7b2c112414..fd7ab1631a 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -13,15 +13,7 @@
     <RepositoryType>git</RepositoryType>
     <RepositoryUrl>https://github.com/json-api-dotnet/JsonApiDotNetCore</RepositoryUrl>
   </PropertyGroup>
-  <PropertyGroup>
-    <IsWindows Condition="'$(OS)' == 'Windows_NT'">true</IsWindows>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
-    <DocumentationFile>bin\Release\netstandard2.0\JsonApiDotNetCore.xml</DocumentationFile>
-  </PropertyGroup>
-  <ItemGroup Condition="$(IsWindows)">
-    <PackageReference Include="docfx.console" Version="2.33.0" />
-  </ItemGroup>
+
   <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
@@ -31,4 +23,15 @@
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
   </ItemGroup>
 
+  <!-- XML documentation -->
+  <PropertyGroup>
+    <IsWindows Condition="'$(OS)' == 'Windows_NT'">true</IsWindows>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+    <DocumentationFile>bin\Release\netstandard2.0\JsonApiDotNetCore.xml</DocumentationFile>
+  </PropertyGroup>
+  <ItemGroup Condition="$(IsWindows)=='true'">
+    <PackageReference Include="docfx.console" Version="2.33.0" />
+  </ItemGroup>
+
 </Project>

From 82824b164c9406edef285d9b71fa433ea0356eec Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 27 Mar 2018 09:09:53 -0500
Subject: [PATCH 110/227] remove support for JsonPointers

---
 .../Extensions/JObjectExtensions.cs           |  22 ---
 .../JsonApiDotNetCore.csproj                  |   2 +-
 .../Models/Pointers/OperationsPointer.cs      | 108 ------------
 .../Models/Pointers/Pointer.cs                |  22 ---
 src/JsonApiDotNetCore/api/.manifest           |   1 -
 .../Models/Pointers/OperationsPointerTests.cs | 164 ------------------
 6 files changed, 1 insertion(+), 318 deletions(-)
 delete mode 100644 src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
 delete mode 100644 src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
 delete mode 100644 src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
 delete mode 100644 test/UnitTests/Models/Pointers/OperationsPointerTests.cs

diff --git a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs b/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
deleted file mode 100644
index 9871258b54..0000000000
--- a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Newtonsoft.Json.Linq;
-using Newtonsoft.Json.Schema;
-using JsonApiDotNetCore.Models.Pointers;
-
-namespace JsonApiDotNetCore.Extensions
-{
-    public static class JObjectExtensions
-    {
-        internal static bool TryParse<TPointer, TPointerBase>(this JObject obj, JSchema schema, out Pointer<TPointerBase> pointer)
-            where TPointer : Pointer<TPointerBase>, new()
-        {
-            if (obj.IsValid(schema))
-            {
-                pointer = obj.ToObject<TPointer>();
-                return true;
-            }
-
-            pointer = null;
-            return false;
-        }
-    }
-}
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index fd7ab1631a..092dd2abcc 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -5,6 +5,7 @@
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>
   </PropertyGroup>
+
   <PropertyGroup>
     <PackageTags>jsonapi;dotnet core;emberjs;ember</PackageTags>
     <PackageProjectUrl>https://github.com/json-api-dotnet/JsonApiDotNetCore</PackageProjectUrl>
@@ -19,7 +20,6 @@
     <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
     <PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftLoggingVersion)" />
-    <PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.2" />
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
   </ItemGroup>
 
diff --git a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
deleted file mode 100644
index 53cdcfec06..0000000000
--- a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using System;
-using System.Collections.Generic;
-using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Models.Operations;
-
-namespace JsonApiDotNetCore.Models.Pointers
-{
-    internal class OperationsPointer : Pointer<Operation>
-    {
-        /// <exception cref="ArgumentNullException"></exception>
-        /// <exception cref="ArgumentException"></exception>
-        /// <exception cref="InvalidOperationException"></exception>
-        /// <exception cref="JsonApiException"></exception>
-        public override object GetValue(object root)
-        {
-            if (root == null) throw new ArgumentNullException(nameof(root));
-            if (PointerAddress == null) throw new InvalidOperationException("Cannot get pointer value from null PointerAddress");
-
-            if (root is List<Operation> operations)
-                return GetValueFromRoot(operations);
-
-            throw new ArgumentException(nameof(root));
-        }
-
-        private object GetValueFromRoot(List<Operation> operations)
-        {
-            var pathSegments = PointerAddress.ToLower().Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
-
-            if (pathSegments.Length < 4)
-                throw BadRequestException("number of segments", pathSegments.Length);
-
-            if (pathSegments[0] != "operations")
-                throw BadRequestException("prefix", pathSegments[0]);
-
-            // /operations/{operationIndex} → operations = [...]
-            if (int.TryParse(pathSegments[1], out int operationIndex))
-                return GetValueFromOperation(operations[operationIndex], pathSegments);
-            else
-                throw BadRequestException("operation index", operationIndex);
-        }
-
-        private object GetValueFromOperation(Operation operation, string[] pathSegments)
-        {
-            var operationPropertyName = pathSegments[2];
-
-            // /operations/0/ref → ref = {...}
-            if (operationPropertyName == "ref")
-                return GetValueFromRef(operation.Ref, pathSegments);
-
-            // /operations/0/data → data = {...}
-            if (operation.DataIsList == false)
-                return GetValueFromData(operation.DataObject, pathSegments, segementStartIndex: 3);
-
-            // /operations/0/data/{dataIndex} → data = [...]
-            if (int.TryParse(pathSegments[3], out int dataIndex))
-            {
-                if (operation.DataList.Count >= dataIndex - 1)
-                    return GetValueFromData(operation.DataList[dataIndex], pathSegments, segementStartIndex: 4);
-                throw BadRequestException("data index", dataIndex, "Pointer references an index in the data array that cannot be found at the specified position.");
-            }
-            else
-            {
-                throw BadRequestException("data index", dataIndex, "Pointer segement should provide array index but could not be parsed to an integer.");
-            }
-        }
-
-        private object GetValueFromRef(ResourceReference reference, string[] pathSegments)
-        {
-            const int segementStartIndex = 3;
-
-            // /operations/0/ref/{dataPropertyName}
-            if (pathSegments.Length <= segementStartIndex)
-                throw BadRequestException("length", pathSegments.Length, "Pointer does not contain enough segments to locate ref property.");
-
-            var dataPropertyName = pathSegments[segementStartIndex];
-            switch (dataPropertyName)
-            {
-                case "id":
-                    return reference.Id;
-                case "type":
-                    return reference.Type;
-                default:
-                    throw BadRequestException("ref property name", dataPropertyName, "Only 'id' and 'type' pointers are supported.");
-            }
-        }
-
-        private object GetValueFromData(DocumentData data, string[] pathSegments, int segementStartIndex)
-        {
-            // /operations/0/data/{dataPropertyName}
-            if (pathSegments.Length <= segementStartIndex)
-                throw BadRequestException("length", pathSegments.Length, "Pointer does not contain enough segments to locate data property.");
-
-            var dataPropertyName = pathSegments[segementStartIndex];
-            switch (dataPropertyName)
-            {
-                case "id":
-                    return data.Id;
-                case "type":
-                    return data.Type;
-                default:
-                    throw BadRequestException("data property name", dataPropertyName, "Only 'id' and 'type' pointers are supported.");
-            }
-        }
-
-        private JsonApiException BadRequestException(string condition, object value, string extraDetail = null)
-            => new JsonApiException(400, $"Operations pointer has invalid {condition} '{value}' in pointer '{PointerAddress}'. {extraDetail}");
-    }
-}
diff --git a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs b/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
deleted file mode 100644
index d5e3a7924b..0000000000
--- a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Schema;
-
-namespace JsonApiDotNetCore.Models.Pointers
-{
-    internal abstract class Pointer<TPointerBase>
-    {
-        public static JSchema JsonSchema { get; } = JSchema.Parse("{ 'pointer': {'type': 'string'} }");
-
-        /// <summary>
-        /// Location represented by the pointer
-        /// </summary>
-        /// <example>/operations/0/data/id</example>
-        [JsonProperty("pointer")]
-        public string PointerAddress { get; set; }
-
-        /// <summary>
-        /// Get the value located at the PointerAddress in the supplied object
-        /// </summary>
-        public abstract object GetValue(object root);
-    }
-}
diff --git a/src/JsonApiDotNetCore/api/.manifest b/src/JsonApiDotNetCore/api/.manifest
index 6aa4a40924..211035306f 100644
--- a/src/JsonApiDotNetCore/api/.manifest
+++ b/src/JsonApiDotNetCore/api/.manifest
@@ -217,7 +217,6 @@
   "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApiInternals(Microsoft.Extensions.DependencyInjection.IServiceCollection,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
   "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApiInternals``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
   "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.SerializeAsJsonApi(Microsoft.AspNetCore.Mvc.MvcOptions,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml",
-  "JsonApiDotNetCore.Extensions.JObjectExtensions": "JsonApiDotNetCore.Extensions.JObjectExtensions.yml",
   "JsonApiDotNetCore.Extensions.StringExtensions": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
   "JsonApiDotNetCore.Extensions.StringExtensions.Dasherize(System.String)": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
   "JsonApiDotNetCore.Extensions.StringExtensions.ToProperCase(System.String)": "JsonApiDotNetCore.Extensions.StringExtensions.yml",
diff --git a/test/UnitTests/Models/Pointers/OperationsPointerTests.cs b/test/UnitTests/Models/Pointers/OperationsPointerTests.cs
deleted file mode 100644
index 9aafc284dc..0000000000
--- a/test/UnitTests/Models/Pointers/OperationsPointerTests.cs
+++ /dev/null
@@ -1,164 +0,0 @@
-using System.Collections.Generic;
-using JsonApiDotNetCore.Models.Operations;
-using JsonApiDotNetCore.Models.Pointers;
-using Newtonsoft.Json;
-using Xunit;
-
-namespace UnitTests.Models.Pointers
-{
-    public class OperationsPointerTests
-    {
-        [Fact]
-        public void GetValue_Can_Get_Value_From_Ref_Id()
-        {
-            // arrange
-            var json = @"[
-                {
-                    ""op"": ""add"",
-                    ""ref"": {
-                        ""type"": ""articles"",
-                        ""id"": ""1""
-                    }
-                }]";
-            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
-            var pointerJson = @"{ ""pointer"": ""/operations/0/ref/id"" }";
-            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
-            var value = pointer.GetValue(operations);
-            Assert.Equal("1", value.ToString());
-        }
-
-        [Fact]
-        public void GetValue_Can_Get_Value_From_Data_Id()
-        {
-            // arrange
-            var json = @"[
-                {
-                    ""op"": ""add"",
-                    ""data"": {
-                        ""id"": ""1"",
-                        ""type"": ""authors"",
-                        ""attributes"": {
-                            ""name"": ""dgeb""
-                        }
-                    }
-                }]";
-            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
-            var pointerJson = @"{ ""pointer"": ""/operations/0/data/id"" }";
-            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
-            var value = pointer.GetValue(operations);
-            Assert.Equal("1", value.ToString());
-        }
-
-        [Fact]
-        public void GetValue_Can_Get_Value_From_Data_Type()
-        {
-            // arrange
-            var json = @"[
-                {
-                    ""op"": ""add"",
-                    ""data"": {
-                        ""id"": ""1"",
-                        ""type"": ""authors"",
-                        ""attributes"": {
-                            ""name"": ""dgeb""
-                        }
-                    }
-                }]";
-            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
-            var pointerJson = @"{ ""pointer"": ""/operations/0/data/type"" }";
-            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
-            var value = pointer.GetValue(operations);
-            Assert.Equal("authors", value.ToString());
-        }
-
-        [Fact]
-        public void GetValue_Can_Get_Value_From_ListData_Id()
-        {
-            // arrange
-            var json = @"[
-                {
-                    ""op"": ""get"",
-                    ""data"": [{
-                        ""id"": ""1"",
-                        ""type"": ""authors"",
-                        ""attributes"": {
-                            ""name"": ""dgeb""
-                        }
-                    }, {
-                        ""id"": ""2"",
-                        ""type"": ""authors"",
-                        ""attributes"": {
-                            ""name"": ""jaredcnance""
-                        }
-                    }]
-                }]";
-            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
-            var pointerJson = @"{ ""pointer"": ""/operations/0/data/1/id"" }";
-            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
-            var value = pointer.GetValue(operations);
-            Assert.Equal("2", value.ToString());
-        }
-
-        [Fact]
-        public void GetValue_Can_Get_Value_From_Second_Operations_Data_Id()
-        {
-            // arrange
-            var json = @"[
-                {
-                    ""op"": ""get"",
-                    ""data"": {
-                        ""id"": ""1"",
-                        ""type"": ""authors"",
-                        ""attributes"": {
-                            ""name"": ""dgeb""
-                        }
-                    }
-                },{
-                    ""op"": ""get"",
-                    ""data"": {
-                        ""id"": ""2"",
-                        ""type"": ""authors"",
-                        ""attributes"": {
-                            ""name"": ""jaredcnance""
-                        }
-                    }
-                }]";
-            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
-            var pointerJson = @"{ ""pointer"": ""/operations/1/data/id"" }";
-            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
-            var value = pointer.GetValue(operations);
-            Assert.Equal("2", value.ToString());
-        }
-
-        [Fact]
-        public void GetValue_Can_Get_Value_From_Second_Operations_Data_Type()
-        {
-            // arrange
-            var json = @"[
-                {
-                    ""op"": ""get"",
-                    ""data"": {
-                        ""id"": ""1"",
-                        ""type"": ""authors"",
-                        ""attributes"": {
-                            ""name"": ""dgeb""
-                        }
-                    }
-                },{
-                    ""op"": ""get"",
-                    ""data"": {
-                        ""id"": ""1"",
-                        ""type"": ""articles"",
-                        ""attributes"": {
-                            ""name"": ""JSON API paints my bikeshed!""
-                        }
-                    }
-                }]";
-            var operations = JsonConvert.DeserializeObject<List<Operation>>(json);
-            var pointerJson = @"{ ""pointer"": ""/operations/1/data/type"" }";
-            var pointer = JsonConvert.DeserializeObject<OperationsPointer>(pointerJson);
-            var value = pointer.GetValue(operations);
-            Assert.Equal("articles", value.ToString());
-        }
-    }
-}
\ No newline at end of file

From 4ef0d79ec028a0f99471b772089a5adeecdc8a37 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 29 Mar 2018 06:13:53 -0500
Subject: [PATCH 111/227] fix(OperationProcessorResolver): do not cache
 opProcessors

---
 .../Operations/OperationProcessorResolver.cs  | 54 +++++++++----------
 1 file changed, 24 insertions(+), 30 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
index 13714edbf3..4215507bc2 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -1,30 +1,42 @@
-using System.Collections.Concurrent;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Services.Operations.Processors;
 
 namespace JsonApiDotNetCore.Services.Operations
 {
+    /// <summary>
+    /// Used to resolve <see cref="IOpProcessor"/> at runtime based on the required operation
+    /// </summary>
     public interface IOperationProcessorResolver
     {
+        /// <summary>
+        /// Locates the correct <see cref="CreateOpProcessor{T, TId}"/>
+        /// </summary>
         IOpProcessor LocateCreateService(Operation operation);
+
+        /// <summary>
+        /// Locates the correct <see cref="GetOpProcessor{T, TId}"/>
+        /// </summary>
         IOpProcessor LocateGetService(Operation operation);
+
+        /// <summary>
+        /// Locates the correct <see cref="RemoveOpProcessor{T, TId}"/>
+        /// </summary>
         IOpProcessor LocateRemoveService(Operation operation);
+
+        /// <summary>
+        /// Locates the correct <see cref="UpdateOpProcessor{T, TId}"/>
+        /// </summary>
         IOpProcessor LocateUpdateService(Operation operation);
     }
 
+    /// <inheritdoc />
     public class OperationProcessorResolver : IOperationProcessorResolver
     {
         private readonly IGenericProcessorFactory _processorFactory;
         private readonly IJsonApiContext _context;
 
-        // processor caches -- since there is some associated cost with creating the processors, we store them in memory
-        // to reduce the cost of subsequent requests. in the future, this may be moved into setup code run at startup
-        private ConcurrentDictionary<string, IOpProcessor> _createOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
-        private ConcurrentDictionary<string, IOpProcessor> _getOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
-        private ConcurrentDictionary<string, IOpProcessor> _removeOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
-        private ConcurrentDictionary<string, IOpProcessor> _updateOpProcessors = new ConcurrentDictionary<string, IOpProcessor>();
-
+        /// <nodoc />
         public OperationProcessorResolver(
             IGenericProcessorFactory processorFactory,
             IJsonApiContext context)
@@ -33,73 +45,55 @@ public OperationProcessorResolver(
             _context = context;
         }
 
-        // TODO: there may be some optimizations here around the cache such as not caching processors
-        // if the request only contains a single op
+        /// <inheritdoc />
         public IOpProcessor LocateCreateService(Operation operation)
         {
             var resource = operation.GetResourceTypeName();
 
-            if (_createOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
-                return cachedProcessor;
-
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
             var processor = _processorFactory.GetProcessor<IOpProcessor>(
                 typeof(ICreateOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
             );
 
-            _createOpProcessors[resource] = processor;
-
             return processor;
         }
 
+        /// <inheritdoc />
         public IOpProcessor LocateGetService(Operation operation)
         {
             var resource = operation.GetResourceTypeName();
 
-            if (_getOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
-                return cachedProcessor;
-
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
             var processor = _processorFactory.GetProcessor<IOpProcessor>(
                 typeof(IGetOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
             );
 
-            _getOpProcessors[resource] = processor;
-
             return processor;
         }
 
+        /// <inheritdoc />
         public IOpProcessor LocateRemoveService(Operation operation)
         {
             var resource = operation.GetResourceTypeName();
 
-            if (_removeOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
-                return cachedProcessor;
-
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
             var processor = _processorFactory.GetProcessor<IOpProcessor>(
                 typeof(IRemoveOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
             );
 
-            _removeOpProcessors[resource] = processor;
-
             return processor;
         }
 
+        /// <inheritdoc />
         public IOpProcessor LocateUpdateService(Operation operation)
         {
             var resource = operation.GetResourceTypeName();
 
-            if (_updateOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor))
-                return cachedProcessor;
-
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
             var processor = _processorFactory.GetProcessor<IOpProcessor>(
                 typeof(IUpdateOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
             );
 
-            _updateOpProcessors[resource] = processor;
-
             return processor;
         }
     }

From a6d6ca6f76a02864af2e3d746c1a51cb0e4667cb Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 29 Mar 2018 06:40:48 -0500
Subject: [PATCH 112/227] return 404 if get by id returns null

---
 .../Operations/Processors/GetOpProcessor.cs   |  8 ++
 .../Get/GetByIdTests.cs                       | 78 +++++++++++++++++++
 test/OperationsExampleTests/Get/GetTests.cs   | 32 +-------
 3 files changed, 87 insertions(+), 31 deletions(-)
 create mode 100644 test/OperationsExampleTests/Get/GetByIdTests.cs

diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
index 8bd5b2b0f4..bbcdf0d8a0 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
@@ -90,6 +90,14 @@ private async Task<object> GetByIdAsync(Operation operation)
         {
             var id = TypeHelper.ConvertType<TId>(operation.Ref.Id);
             var result = await _getById.GetAsync(id);
+
+            // this is a bit ugly but we need to bomb the entire transaction if the entity cannot be found
+            // in the future it would probably be better to return a result status along with the doc to 
+            // avoid throwing exceptions on 4xx errors.
+            // consider response type (status, document)
+            if (result == null)
+                throw new JsonApiException(404, $"Could not find '{operation.Ref.Type}' record with id '{operation.Ref.Id}'");
+
             var doc = _documentBuilder.GetData(
                 _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
                 result);
diff --git a/test/OperationsExampleTests/Get/GetByIdTests.cs b/test/OperationsExampleTests/Get/GetByIdTests.cs
new file mode 100644
index 0000000000..1dee2867ce
--- /dev/null
+++ b/test/OperationsExampleTests/Get/GetByIdTests.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using Bogus;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCoreExample.Data;
+using OperationsExampleTests.Factories;
+using Xunit;
+
+namespace OperationsExampleTests
+{
+    public class GetTests : Fixture, IDisposable
+    {
+        private readonly Faker _faker = new Faker();
+
+        [Fact]
+        public async Task Can_Get_Author_By_Id()
+        {
+            // arrange
+            var context = GetService<AppDbContext>();
+            var author = AuthorFactory.Get();
+            context.Authors.Add(author);
+            context.SaveChanges();
+
+            var content = new
+            {
+                operations = new[] {
+                    new Dictionary<string, object> {
+                        { "op", "get"},
+                        { "ref",  new { type = "authors", id = author.StringId } }
+                    }
+                }
+            };
+
+            // act
+            var result = await PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(result.response);
+            Assert.NotNull(result.data);
+            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
+            Assert.Equal(1, result.data.Operations.Count);
+            Assert.Equal(author.Id.ToString(), result.data.Operations.Single().DataObject.Id);
+        }
+
+        [Fact]
+        public async Task Get_Author_By_Id_Returns_404_If_NotFound()
+        {
+            // arrange
+            var authorId = _faker.Random.Int(max: 0).ToString();
+
+            var content = new
+            {
+                operations = new[] {
+                    new Dictionary<string, object> {
+                        { "op", "get"},
+                        { "ref",  new { type = "authors", id = authorId } }
+                    }
+                }
+            };
+
+            // act
+            var (response, data) = await PatchAsync<ErrorCollection>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(response);
+            Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
+            Assert.NotNull(data);
+            Assert.Equal(1, data.Errors.Count);
+            Assert.True(data.Errors[0].Detail.Contains("authors"), "The error detail should contain the name of the entity that could not be found.");
+            Assert.True(data.Errors[0].Detail.Contains(authorId), "The error detail should contain the entity id that could not be found");
+            Assert.True(data.Errors[0].Title.Contains("operation[0]"), "The error title should contain the operation identifier that failed");
+        }
+    }
+}
diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs
index 1bf0393fa8..bf1c15e3a4 100644
--- a/test/OperationsExampleTests/Get/GetTests.cs
+++ b/test/OperationsExampleTests/Get/GetTests.cs
@@ -11,7 +11,7 @@
 
 namespace OperationsExampleTests
 {
-    public class GetTests : Fixture, IDisposable
+    public class GetByIdTests : Fixture, IDisposable
     {
         private readonly Faker _faker = new Faker();
 
@@ -46,36 +46,6 @@ public async Task Can_Get_Authors()
             Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
             Assert.Equal(1, result.data.Operations.Count);
             Assert.Equal(expectedCount, result.data.Operations.Single().DataList.Count);
-        }
-
-        [Fact]
-        public async Task Can_Get_Author_By_Id()
-        {
-            // arrange
-            var context = GetService<AppDbContext>();
-            var author = AuthorFactory.Get();
-            context.Authors.Add(author);
-            context.SaveChanges();
-
-            var content = new
-            {
-                operations = new[] {
-                    new Dictionary<string, object> {
-                        { "op", "get"},
-                        { "ref",  new { type = "authors", id = author.StringId } }
-                    }
-                }
-            };
-
-            // act
-            var result = await PatchAsync<OperationsDocument>("api/bulk", content);
-
-            // assert
-            Assert.NotNull(result.response);
-            Assert.NotNull(result.data);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(1, result.data.Operations.Count);
-            Assert.Equal(author.Id.ToString(), result.data.Operations.Single().DataObject.Id);
         }
     }
 }

From 9e18ab3339314c71a90633017165a63868f04dc6 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 29 Mar 2018 09:15:13 -0500
Subject: [PATCH 113/227] introduce Is method on attributes for performing case
 insensitive comparisons

---
 .../Internal/ContextGraph.cs                  |  8 +--
 .../Internal/Query/AttrFilterQuery.cs         | 10 ++--
 .../Internal/Query/RelatedAttrFilterQuery.cs  | 13 ++---
 src/JsonApiDotNetCore/Models/AttrAttribute.cs |  6 ++
 .../Models/RelationshipAttribute.cs           |  8 ++-
 src/JsonApiDotNetCore/Services/QueryParser.cs | 57 ++++++++++++-------
 6 files changed, 61 insertions(+), 41 deletions(-)

diff --git a/src/JsonApiDotNetCore/Internal/ContextGraph.cs b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
index bc3f037bf2..d21231f067 100644
--- a/src/JsonApiDotNetCore/Internal/ContextGraph.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
@@ -9,8 +9,8 @@ public class ContextGraph : IContextGraph
         private List<ContextEntity> _entities;
 
         public ContextGraph() { }
-        
-        public ContextGraph(List<ContextEntity> entities, bool usesDbContext) 
+
+        public ContextGraph(List<ContextEntity> entities, bool usesDbContext)
         {
             _entities = entities;
             UsesDbContext = usesDbContext;
@@ -42,9 +42,9 @@ public string GetRelationshipName<TParent>(string relationshipName)
         {
             var entityType = typeof(TParent);
             return _entities
-                .SingleOrDefault(e => e.EntityType == entityType) 
+                .SingleOrDefault(e => e.EntityType == entityType)
                 ?.Relationships
-                .SingleOrDefault(r => string.Equals(r.PublicRelationshipName, relationshipName, StringComparison.OrdinalIgnoreCase)) 
+                .SingleOrDefault(r => r.Is(relationshipName))
                 ?.InternalRelationshipName;
         }
     }
diff --git a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
index e94f872b54..59bb3f0f83 100644
--- a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
@@ -17,10 +17,10 @@ public AttrFilterQuery(
 
             var attribute = GetAttribute(filterQuery.Attribute);
 
-            if(attribute == null)
+            if (attribute == null)
                 throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
 
-            if(attribute.IsFilterable == false)
+            if (attribute.IsFilterable == false)
                 throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'.");
 
             FilteredAttribute = attribute;
@@ -32,9 +32,7 @@ public AttrFilterQuery(
         public string PropertyValue { get; }
         public FilterOperations FilterOperation { get; }
 
-        private AttrAttribute GetAttribute(string attribute) =>  
-            _jsonApiContext.RequestEntity.Attributes.FirstOrDefault(
-                attr => string.Equals(attr.PublicAttributeName, attribute, StringComparison.OrdinalIgnoreCase)
-            );
+        private AttrAttribute GetAttribute(string attribute) =>
+            _jsonApiContext.RequestEntity.Attributes.FirstOrDefault(attr => attr.Is(attribute));
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
index 52d7c66f41..5ec658873d 100644
--- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
@@ -22,11 +22,11 @@ public RelatedAttrFilterQuery(
                 throw new JsonApiException(400, $"{relationshipArray[1]} is not a valid relationship on {relationshipArray[0]}.");
 
             var attribute = GetAttribute(relationship, relationshipArray[1]);
-            
-            if(attribute == null)
+
+            if (attribute == null)
                 throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
 
-            if(attribute.IsFilterable == false)
+            if (attribute.IsFilterable == false)
                 throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'.");
 
             FilteredRelationship = relationship;
@@ -41,16 +41,13 @@ public RelatedAttrFilterQuery(
         public RelationshipAttribute FilteredRelationship { get; }
 
         private RelationshipAttribute GetRelationship(string propertyName)
-        {
-            return _jsonApiContext.RequestEntity.Relationships
-              .FirstOrDefault(r => string.Equals(r.PublicRelationshipName, propertyName, StringComparison.OrdinalIgnoreCase));
-        }
+            => _jsonApiContext.RequestEntity.Relationships.FirstOrDefault(r => r.Is(propertyName));
 
         private AttrAttribute GetAttribute(RelationshipAttribute relationship, string attribute)
         {
             var relatedContextExntity = _jsonApiContext.ContextGraph.GetContextEntity(relationship.Type);
             return relatedContextExntity.Attributes
-              .FirstOrDefault(a => string.Equals(a.PublicAttributeName, attribute, StringComparison.OrdinalIgnoreCase));
+              .FirstOrDefault(a => a.Is(attribute));
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
index 5be036636d..db61cb56ea 100644
--- a/src/JsonApiDotNetCore/Models/AttrAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
@@ -47,5 +47,11 @@ public void SetValue(object entity, object newValue)
                 propertyInfo.SetValue(entity, convertedValue);
             }
         }
+
+        /// <summary>
+        /// Whether or not the provided exposed name is equivalent to the one defined in on the model
+        /// </summary>
+        public virtual bool Is(string publicRelationshipName)
+            => string.Equals(publicRelationshipName, PublicAttributeName, StringComparison.OrdinalIgnoreCase);
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
index 852b602bea..0dbe6a4670 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
 
 namespace JsonApiDotNetCore.Models
 {
@@ -33,5 +33,11 @@ public override bool Equals(object obj)
             }
             return IsHasMany == attr.IsHasMany && PublicRelationshipName.Equals(attr.PublicRelationshipName);
         }
+
+        /// <summary>
+        /// Whether or not the provided exposed name is equivalent to the one defined in on the model
+        /// </summary>
+        public virtual bool Is(string publicRelationshipName)
+            => string.Equals(publicRelationshipName, PublicRelationshipName, StringComparison.OrdinalIgnoreCase);
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index d9dfab532d..5e705f4bc9 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -8,12 +8,15 @@
 using JsonApiDotNetCore.Models;
 using Microsoft.AspNetCore.Http;
 
-namespace JsonApiDotNetCore.Services {
-    public interface IQueryParser {
+namespace JsonApiDotNetCore.Services
+{
+    public interface IQueryParser
+    {
         QuerySet Parse(IQueryCollection query);
     }
 
-    public class QueryParser : IQueryParser {
+    public class QueryParser : IQueryParser
+    {
         private readonly IControllerContext _controllerContext;
         private readonly JsonApiOptions _options;
 
@@ -30,41 +33,49 @@ public class QueryParser : IQueryParser {
 
         public QueryParser(
             IControllerContext controllerContext,
-            JsonApiOptions options) {
+            JsonApiOptions options)
+        {
             _controllerContext = controllerContext;
             _options = options;
         }
 
-        public virtual QuerySet Parse(IQueryCollection query) {
+        public virtual QuerySet Parse(IQueryCollection query)
+        {
             var querySet = new QuerySet();
-            var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>() ? .QueryParams ?? QueryParams.None;
+            var disabledQueries = _controllerContext.GetControllerAttribute<DisableQueryAttribute>()?.QueryParams ?? QueryParams.None;
 
-            foreach (var pair in query) {
-                if (pair.Key.StartsWith(FILTER)) {
+            foreach (var pair in query)
+            {
+                if (pair.Key.StartsWith(FILTER))
+                {
                     if (disabledQueries.HasFlag(QueryParams.Filter) == false)
                         querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
                     continue;
                 }
 
-                if (pair.Key.StartsWith(SORT)) {
+                if (pair.Key.StartsWith(SORT))
+                {
                     if (disabledQueries.HasFlag(QueryParams.Sort) == false)
                         querySet.SortParameters = ParseSortParameters(pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith(INCLUDE)) {
+                if (pair.Key.StartsWith(INCLUDE))
+                {
                     if (disabledQueries.HasFlag(QueryParams.Include) == false)
                         querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith(PAGE)) {
+                if (pair.Key.StartsWith(PAGE))
+                {
                     if (disabledQueries.HasFlag(QueryParams.Page) == false)
                         querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith(FIELDS)) {
+                if (pair.Key.StartsWith(FIELDS))
+                {
                     if (disabledQueries.HasFlag(QueryParams.Fields) == false)
                         querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value);
                     continue;
@@ -77,15 +88,17 @@ public virtual QuerySet Parse(IQueryCollection query) {
             return querySet;
         }
 
-        protected virtual List<FilterQuery> ParseFilterQuery(string key, string value) {
+        protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
+        {
             // expected input = filter[id]=1
             // expected input = filter[id]=eq:1
             var queries = new List<FilterQuery>();
 
-            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1];
+            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
 
             var values = value.Split(COMMA);
-            foreach (var val in values) {
+            foreach (var val in values)
+            {
                 (var operation, var filterValue) = ParseFilterOperation(val);
                 queries.Add(new FilterQuery(propertyName, filterValue, operation));
             }
@@ -93,7 +106,8 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value) {
             return queries;
         }
 
-        protected virtual(string operation, string value) ParseFilterOperation(string value) {
+        protected virtual (string operation, string value) ParseFilterOperation(string value)
+        {
             if (value.Length < 3)
                 return (string.Empty, value);
 
@@ -159,7 +173,7 @@ protected virtual List<SortQuery> ParseSortParameters(string value)
 
                 var attribute = GetAttribute(propertyName);
 
-                if(attribute.IsSortable == false)
+                if (attribute.IsSortable == false)
                     throw new JsonApiException(400, $"Sort is not allowed for attribute '{attribute.PublicAttributeName}'.");
 
                 sortParameters.Add(new SortQuery(direction, attribute));
@@ -168,7 +182,8 @@ protected virtual List<SortQuery> ParseSortParameters(string value)
             return sortParameters;
         }
 
-        protected virtual List<string> ParseIncludedRelationships(string value) {
+        protected virtual List<string> ParseIncludedRelationships(string value)
+        {
             const string NESTED_DELIMITER = ".";
             if (value.Contains(NESTED_DELIMITER))
                 throw new JsonApiException(400, "Deeply nested relationships are not supported");
@@ -195,7 +210,7 @@ protected virtual List<string> ParseFieldsQuery(string key, string value)
             {
                 var attr = _controllerContext.RequestEntity
                     .Attributes
-                    .SingleOrDefault(a => string.Equals(a.PublicAttributeName, field, StringComparison.OrdinalIgnoreCase));
+                    .SingleOrDefault(a => a.Is(field));
 
                 if (attr == null) throw new JsonApiException(400, $"'{_controllerContext.RequestEntity.EntityName}' does not contain '{field}'.");
 
@@ -213,9 +228,7 @@ protected virtual AttrAttribute GetAttribute(string propertyName)
                 return _controllerContext
                     .RequestEntity
                     .Attributes
-                    .Single(attr =>
-                        string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase)
-                    );
+                    .Single(attr => attr.Is(propertyName));
             }
             catch (InvalidOperationException e)
             {

From 59fc19a539cfb1c23a8ab827a98642013dcb0b7e Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 29 Mar 2018 09:20:08 -0500
Subject: [PATCH 114/227] support get relationship requests in operations

---
 .../Builders/DocumentBuilderOptions.cs        |  6 +--
 .../Configuration/JsonApiOptions.cs           |  9 ++--
 .../IServiceCollectionExtensions.cs           |  3 ++
 .../Services/EntityResourceService.cs         |  2 +
 .../Operations/Processors/GetOpProcessor.cs   | 48 +++++++++++++++--
 src/JsonApiDotNetCore/api/.manifest           |  6 ++-
 .../Get/GetRelationshipTests.cs               | 52 +++++++++++++++++++
 7 files changed, 111 insertions(+), 15 deletions(-)
 create mode 100644 test/OperationsExampleTests/Get/GetRelationshipTests.cs

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs
index ec19977313..0596d8ce3c 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs
@@ -1,10 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
 namespace JsonApiDotNetCore.Builders
 {
-    public struct DocumentBuilderOptions 
+    public struct DocumentBuilderOptions
     {
         public DocumentBuilderOptions(bool omitNullValuedAttributes = false)
         {
diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index abcb3f6dbf..dd76eeba2c 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -52,7 +52,7 @@ public class JsonApiOptions
         /// <code>options.AllowClientGeneratedIds = true;</code>
         /// </example>
         public bool AllowClientGeneratedIds { get; set; }
-        
+
         /// <summary>
         /// The graph of all resources exposed by this application.
         /// </summary>
@@ -107,10 +107,11 @@ public class JsonApiOptions
         /// <summary>
         /// Whether or not to allow json:api v1.1 operation requests.
         /// This is a beta feature and there may be breaking changes
-        /// in subsequent releases.
+        /// in subsequent releases. For now, it should be considered
+        /// experimental.
         /// </summary>
         /// <remarks>
-        /// This will be enabled by default in JsonApiDotNetCore v2.2.1
+        /// This will be enabled by default in a subsequent patch JsonApiDotNetCore v2.2.x
         /// </remarks>
         public bool EnableOperations { get; set; }
 
@@ -144,7 +145,7 @@ public void BuildContextGraph(Action<IContextGraphBuilder> builder)
             ContextGraph = ContextGraphBuilder.Build();
         }
 
-        public void EnableExtension(JsonApiExtension extension) 
+        public void EnableExtension(JsonApiExtension extension)
             => EnabledExtensions.Add(extension);
 
         internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder();
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 0b13755edc..807d21c018 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -109,6 +109,9 @@ public static void AddJsonApiInternals(
             services.AddScoped(typeof(IGetByIdService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IGetByIdService<,>), typeof(EntityResourceService<,>));
 
+            services.AddScoped(typeof(IGetRelationshipService<,>), typeof(EntityResourceService<>));
+            services.AddScoped(typeof(IGetRelationshipService<,>), typeof(EntityResourceService<,>));
+
             services.AddScoped(typeof(IUpdateService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IUpdateService<,>), typeof(EntityResourceService<,>));
 
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index af86692166..91eabb9cfd 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -96,6 +96,8 @@ public virtual async Task<object> GetRelationshipAsync(TId id, string relationsh
             _logger.LogTrace($"Looking up '{relationshipName}'...");
 
             var entity = await _entities.GetAndIncludeAsync(id, relationshipName);
+            // TODO: it would be better if we could distinguish whether or not the relationship was not found,
+            // vs the relationship not being set on the instance of T
             if (entity == null)
                 throw new JsonApiException(404, $"Relationship {relationshipName} not found.");
 
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
index bbcdf0d8a0..d8793d016c 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
@@ -1,4 +1,6 @@
+using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Internal;
@@ -8,41 +10,57 @@
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
+    /// <summary>
+    /// Handles all "<see cref="OperationCode.get"/>" operations 
+    /// </summary>
+    /// <typeparam name="T">The resource type</typeparam>
     public interface IGetOpProcessor<T> : IOpProcessor
         where T : class, IIdentifiable<int>
     { }
 
+    /// <summary>
+    ///  Handles all "<see cref="OperationCode.get"/>" operations 
+    /// </summary>
+    /// <typeparam name="T">The resource type</typeparam>
+    /// <typeparam name="TId">The resource identifier type</typeparam>
     public interface IGetOpProcessor<T, TId> : IOpProcessor
         where T : class, IIdentifiable<TId>
     { }
 
+    /// <inheritdoc />
     public class GetOpProcessor<T> : GetOpProcessor<T, int>
         where T : class, IIdentifiable<int>
     {
+        /// <inheritdoc />
         public GetOpProcessor(
             IGetAllService<T, int> getAll,
             IGetByIdService<T, int> getById,
+            IGetRelationshipService<T, int> getRelationship,
             IJsonApiDeSerializer deSerializer,
             IDocumentBuilder documentBuilder,
             IContextGraph contextGraph,
             IJsonApiContext jsonApiContext
-        ) : base(getAll, getById, deSerializer, documentBuilder, contextGraph, jsonApiContext)
+        ) : base(getAll, getById, getRelationship, deSerializer, documentBuilder, contextGraph, jsonApiContext)
         { }
     }
 
+    /// <inheritdoc />
     public class GetOpProcessor<T, TId> : IGetOpProcessor<T, TId>
          where T : class, IIdentifiable<TId>
     {
         private readonly IGetAllService<T, TId> _getAll;
         private readonly IGetByIdService<T, TId> _getById;
+        private readonly IGetRelationshipService<T, TId> _getRelationship;
         private readonly IJsonApiDeSerializer _deSerializer;
         private readonly IDocumentBuilder _documentBuilder;
         private readonly IContextGraph _contextGraph;
         private readonly IJsonApiContext _jsonApiContext;
 
+        /// <inheritdoc />
         public GetOpProcessor(
             IGetAllService<T, TId> getAll,
             IGetByIdService<T, TId> getById,
+            IGetRelationshipService<T, TId> getRelationship,
             IJsonApiDeSerializer deSerializer,
             IDocumentBuilder documentBuilder,
             IContextGraph contextGraph,
@@ -50,12 +68,14 @@ public GetOpProcessor(
         {
             _getAll = getAll;
             _getById = getById;
+            _getRelationship = getRelationship;
             _deSerializer = deSerializer;
             _documentBuilder = documentBuilder;
             _contextGraph = contextGraph;
             _jsonApiContext = jsonApiContext.ApplyContext<T>(this);
         }
 
+        /// <inheritdoc />
         public async Task<Operation> ProcessAsync(Operation operation)
         {
             var operationResult = new Operation
@@ -63,9 +83,11 @@ public async Task<Operation> ProcessAsync(Operation operation)
                 Op = OperationCode.get
             };
 
-            operationResult.Data = string.IsNullOrWhiteSpace(operation.Ref.Id?.ToString())
+            operationResult.Data = string.IsNullOrWhiteSpace(operation.Ref.Id)
             ? await GetAllAsync(operation)
-            : await GetByIdAsync(operation);
+            : string.IsNullOrWhiteSpace(operation.Ref.Relationship)
+                ? await GetByIdAsync(operation)
+                : await GetRelationshipAsync(operation);
 
             return operationResult;
         }
@@ -88,7 +110,7 @@ private async Task<object> GetAllAsync(Operation operation)
 
         private async Task<object> GetByIdAsync(Operation operation)
         {
-            var id = TypeHelper.ConvertType<TId>(operation.Ref.Id);
+            var id = GetReferenceId(operation);
             var result = await _getById.GetAsync(id);
 
             // this is a bit ugly but we need to bomb the entire transaction if the entity cannot be found
@@ -104,5 +126,23 @@ private async Task<object> GetByIdAsync(Operation operation)
 
             return doc;
         }
+
+        private async Task<object> GetRelationshipAsync(Operation operation)
+        {
+            var id = GetReferenceId(operation);
+            var result = await _getRelationship.GetRelationshipAsync(id, operation.Ref.Relationship);
+
+            // TODO: need a better way to get the ContextEntity from a relationship name
+            // when no generic parameter is available
+            var relationshipType = _contextGraph.GetContextEntity(operation.GetResourceTypeName())
+                .Relationships.Single(r => r.Is(operation.Ref.Relationship)).Type;
+            var relatedContextEntity = _jsonApiContext.ContextGraph.GetContextEntity(relationshipType);
+
+            var doc = _documentBuilder.GetData(relatedContextEntity, result as IIdentifiable); // TODO: if this is safe, then it should be cast in the GetRelationshipAsync call
+
+            return doc;
+        }
+
+        private TId GetReferenceId(Operation operation) => TypeHelper.ConvertType<TId>(operation.Ref.Id);
     }
 }
diff --git a/src/JsonApiDotNetCore/api/.manifest b/src/JsonApiDotNetCore/api/.manifest
index 211035306f..43cb398351 100644
--- a/src/JsonApiDotNetCore/api/.manifest
+++ b/src/JsonApiDotNetCore/api/.manifest
@@ -381,6 +381,7 @@
   "JsonApiDotNetCore.Models.AttrAttribute.#ctor(System.String,System.Boolean,System.Boolean,System.Boolean)": "JsonApiDotNetCore.Models.AttrAttribute.yml",
   "JsonApiDotNetCore.Models.AttrAttribute.GetValue(System.Object)": "JsonApiDotNetCore.Models.AttrAttribute.yml",
   "JsonApiDotNetCore.Models.AttrAttribute.InternalAttributeName": "JsonApiDotNetCore.Models.AttrAttribute.yml",
+  "JsonApiDotNetCore.Models.AttrAttribute.Is(System.String)": "JsonApiDotNetCore.Models.AttrAttribute.yml",
   "JsonApiDotNetCore.Models.AttrAttribute.IsFilterable": "JsonApiDotNetCore.Models.AttrAttribute.yml",
   "JsonApiDotNetCore.Models.AttrAttribute.IsImmutable": "JsonApiDotNetCore.Models.AttrAttribute.yml",
   "JsonApiDotNetCore.Models.AttrAttribute.IsSortable": "JsonApiDotNetCore.Models.AttrAttribute.yml",
@@ -459,6 +460,7 @@
   "JsonApiDotNetCore.Models.RelationshipAttribute.DocumentLinks": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
   "JsonApiDotNetCore.Models.RelationshipAttribute.Equals(System.Object)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
   "JsonApiDotNetCore.Models.RelationshipAttribute.InternalRelationshipName": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
+  "JsonApiDotNetCore.Models.RelationshipAttribute.Is(System.String)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
   "JsonApiDotNetCore.Models.RelationshipAttribute.IsHasMany": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
   "JsonApiDotNetCore.Models.RelationshipAttribute.IsHasOne": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
   "JsonApiDotNetCore.Models.RelationshipAttribute.PublicRelationshipName": "JsonApiDotNetCore.Models.RelationshipAttribute.yml",
@@ -638,9 +640,9 @@
   "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`2.#ctor(JsonApiDotNetCore.Services.ICreateService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-1.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IGetAllService{`0,System.Int32},JsonApiDotNetCore.Services.IGetByIdService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-1.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IGetAllService{`0,System.Int32},JsonApiDotNetCore.Services.IGetByIdService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-1.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml",
-  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IGetAllService{`0,`1},JsonApiDotNetCore.Services.IGetByIdService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml",
+  "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IGetAllService{`0,`1},JsonApiDotNetCore.Services.IGetByIdService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor-1.yml",
   "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor-2.yml",
diff --git a/test/OperationsExampleTests/Get/GetRelationshipTests.cs b/test/OperationsExampleTests/Get/GetRelationshipTests.cs
new file mode 100644
index 0000000000..03f276da17
--- /dev/null
+++ b/test/OperationsExampleTests/Get/GetRelationshipTests.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using Bogus;
+using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCoreExample.Data;
+using OperationsExampleTests.Factories;
+using Xunit;
+
+namespace OperationsExampleTests
+{
+    public class GetRelationshipTests : Fixture, IDisposable
+    {
+        private readonly Faker _faker = new Faker();
+
+        [Fact]
+        public async Task Can_Get_Article_Author()
+        {
+            // arrange
+            var context = GetService<AppDbContext>();
+            var author = AuthorFactory.Get();
+            var article = ArticleFactory.Get();
+            article.Author = author;
+            context.Articles.Add(article);
+            context.SaveChanges();
+
+            var content = new
+            {
+                operations = new[] {
+                    new Dictionary<string, object> {
+                        { "op", "get"},
+                        { "ref",  new { type = "articles", id = article.StringId, relationship = nameof(article.Author) } }
+                    }
+                }
+            };
+
+            // act
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
+
+            // assert
+            Assert.NotNull(response);
+            Assert.NotNull(data);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Equal(1, data.Operations.Count);
+            var resourceObject = data.Operations.Single().DataObject;
+            Assert.Equal(author.Id.ToString(), resourceObject.Id);
+            Assert.Equal("authors", resourceObject.Type);
+        }
+    }
+}

From 08f71afcb75bf3965b5a25a741f70d85d442a29f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 31 Mar 2018 11:12:20 -0500
Subject: [PATCH 115/227] return 409 for mismatching data types

---
 .../Internal/JsonApiExceptionFactory.cs       | 12 +++++++++--
 src/JsonApiDotNetCore/api/.manifest           | 21 +++++++++++++------
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs b/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
index 20ae9ebc62..159c9abc70 100644
--- a/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs
@@ -8,9 +8,17 @@ public static JsonApiException GetException(Exception exception)
         {
             var exceptionType = exception.GetType();
 
-            if(exceptionType == typeof(JsonApiException))
+            if (exceptionType == typeof(JsonApiException))
                 return (JsonApiException)exception;
-                
+
+            // TODO: this is for mismatching type requests (e.g. posting an author to articles endpoint)
+            // however, we can't actually guarantee that this is the source of this exception
+            // we should probably use an action filter or when we improve the ContextGraph 
+            // we might be able to skip most of deserialization entirely by checking the JToken
+            // directly
+            if (exceptionType == typeof(InvalidCastException))
+                return new JsonApiException(409, exception.Message, exception);
+
             return new JsonApiException(500, exceptionType.Name, exception);
         }
     }
diff --git a/src/JsonApiDotNetCore/api/.manifest b/src/JsonApiDotNetCore/api/.manifest
index 43cb398351..41d94c66fb 100644
--- a/src/JsonApiDotNetCore/api/.manifest
+++ b/src/JsonApiDotNetCore/api/.manifest
@@ -54,6 +54,8 @@
   "JsonApiDotNetCore.Configuration.JsonApiOptions.BuildContextGraph``1(System.Action{JsonApiDotNetCore.Builders.IContextGraphBuilder})": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
   "JsonApiDotNetCore.Configuration.JsonApiOptions.ContextGraph": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
   "JsonApiDotNetCore.Configuration.JsonApiOptions.DefaultPageSize": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.DisableErrorSource": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
+  "JsonApiDotNetCore.Configuration.JsonApiOptions.DisableErrorStackTraces": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
   "JsonApiDotNetCore.Configuration.JsonApiOptions.EnableExtension(JsonApiDotNetCore.Models.JsonApiExtension)": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
   "JsonApiDotNetCore.Configuration.JsonApiOptions.EnableOperations": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
   "JsonApiDotNetCore.Configuration.JsonApiOptions.IncludeTotalRecordCount": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml",
@@ -261,11 +263,15 @@
   "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModel)": "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.yml",
   "JsonApiDotNetCore.Internal.Error": "JsonApiDotNetCore.Internal.Error.yml",
   "JsonApiDotNetCore.Internal.Error.#ctor": "JsonApiDotNetCore.Internal.Error.yml",
-  "JsonApiDotNetCore.Internal.Error.#ctor(System.Int32,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
-  "JsonApiDotNetCore.Internal.Error.#ctor(System.Int32,System.String,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
-  "JsonApiDotNetCore.Internal.Error.#ctor(System.String,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
-  "JsonApiDotNetCore.Internal.Error.#ctor(System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor(System.Int32,System.String,JsonApiDotNetCore.Internal.ErrorMeta,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor(System.Int32,System.String,System.String,JsonApiDotNetCore.Internal.ErrorMeta,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor(System.String,System.String,JsonApiDotNetCore.Internal.ErrorMeta,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.#ctor(System.String,System.String,System.String,JsonApiDotNetCore.Internal.ErrorMeta,System.String)": "JsonApiDotNetCore.Internal.Error.yml",
   "JsonApiDotNetCore.Internal.Error.Detail": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.Meta": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.ShouldSerializeMeta": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.ShouldSerializeSource": "JsonApiDotNetCore.Internal.Error.yml",
+  "JsonApiDotNetCore.Internal.Error.Source": "JsonApiDotNetCore.Internal.Error.yml",
   "JsonApiDotNetCore.Internal.Error.Status": "JsonApiDotNetCore.Internal.Error.yml",
   "JsonApiDotNetCore.Internal.Error.StatusCode": "JsonApiDotNetCore.Internal.Error.yml",
   "JsonApiDotNetCore.Internal.Error.Title": "JsonApiDotNetCore.Internal.Error.yml",
@@ -274,6 +280,9 @@
   "JsonApiDotNetCore.Internal.ErrorCollection.Add(JsonApiDotNetCore.Internal.Error)": "JsonApiDotNetCore.Internal.ErrorCollection.yml",
   "JsonApiDotNetCore.Internal.ErrorCollection.Errors": "JsonApiDotNetCore.Internal.ErrorCollection.yml",
   "JsonApiDotNetCore.Internal.ErrorCollection.GetJson": "JsonApiDotNetCore.Internal.ErrorCollection.yml",
+  "JsonApiDotNetCore.Internal.ErrorMeta": "JsonApiDotNetCore.Internal.ErrorMeta.yml",
+  "JsonApiDotNetCore.Internal.ErrorMeta.FromException(System.Exception)": "JsonApiDotNetCore.Internal.ErrorMeta.yml",
+  "JsonApiDotNetCore.Internal.ErrorMeta.StackTrace": "JsonApiDotNetCore.Internal.ErrorMeta.yml",
   "JsonApiDotNetCore.Internal.Generics": "JsonApiDotNetCore.Internal.Generics.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessor`1": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-1.yml",
   "JsonApiDotNetCore.Internal.Generics.GenericProcessor`1.#ctor(JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-1.yml",
@@ -300,11 +309,11 @@
   "JsonApiDotNetCore.Internal.JsonApiException": "JsonApiDotNetCore.Internal.JsonApiException.yml",
   "JsonApiDotNetCore.Internal.JsonApiException.#ctor(JsonApiDotNetCore.Internal.Error)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
   "JsonApiDotNetCore.Internal.JsonApiException.#ctor(JsonApiDotNetCore.Internal.ErrorCollection)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
-  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
   "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String,System.Exception)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
   "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
-  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
   "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
+  "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.String,System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml",
   "JsonApiDotNetCore.Internal.JsonApiException.GetError": "JsonApiDotNetCore.Internal.JsonApiException.yml",
   "JsonApiDotNetCore.Internal.JsonApiException.GetStatusCode": "JsonApiDotNetCore.Internal.JsonApiException.yml",
   "JsonApiDotNetCore.Internal.JsonApiExceptionFactory": "JsonApiDotNetCore.Internal.JsonApiExceptionFactory.yml",

From 7ba47cd38e0aefe98ee46b8c9496efcf8648a0ea Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Sun, 1 Apr 2018 05:48:14 -0500
Subject: [PATCH 116/227] Update README.md

---
 README.md | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/README.md b/README.md
index f396be824b..c09fe884b6 100644
--- a/README.md
+++ b/README.md
@@ -58,13 +58,3 @@ public class Startup
     }
 }
 ```
-
-## Development Priorities
-
-The current priorities for future development (in order): 
-1. Operations Support ([#150](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/150))
-2. Minor features ([#105](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/105), [#144](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/144), [#162](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/162))
-3. Resource to Entity Mapping ([#112](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/112))
-
-If you're interested in working on any of the above features, take a look at the [Contributing Guide](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/CONTRIBUTING.MD)
-or hop on the project Gitter for more direct communication.

From 3989d3f3fc150baf166bff8d86c0385c93bec1a9 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 4 Apr 2018 15:50:21 -0500
Subject: [PATCH 117/227] fix(ContextGraphBuilder): don't throw if DbContext
 contains non json:api resource

Also begins work for #170
---
 .../Data/AppDbContext.cs                      |  2 +
 .../Models/NonJsonApiResource.cs              |  7 +++
 .../Builders/ContextGraphBuilder.cs           | 53 +++++++++++++++++--
 .../Builders/IContextGraphBuilder.cs          | 15 ------
 .../IApplicationBuilderExtensions.cs          | 38 ++++++++++---
 .../Internal/ContextGraph.cs                  | 32 +++++++++--
 .../Internal/IContextGraph.cs                 | 13 -----
 .../Internal/ValidationResults.cs             | 16 ++++++
 .../Internal/ContextGraphBuilder_Tests.cs     | 48 +++++++++++++++++
 9 files changed, 180 insertions(+), 44 deletions(-)
 create mode 100644 src/Examples/JsonApiDotNetCoreExample/Models/NonJsonApiResource.cs
 delete mode 100644 src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
 delete mode 100644 src/JsonApiDotNetCore/Internal/IContextGraph.cs
 create mode 100644 src/JsonApiDotNetCore/Internal/ValidationResults.cs
 create mode 100644 test/UnitTests/Internal/ContextGraphBuilder_Tests.cs

diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
index 4266ca9741..4b9a40f7fd 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
@@ -37,5 +37,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
 
         public DbSet<Article> Articles { get; set; }
         public DbSet<Author> Authors { get; set; }
+
+        public DbSet<NonJsonApiResource> NonJsonApiResources { get; set; }
     }
 }
diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/NonJsonApiResource.cs b/src/Examples/JsonApiDotNetCoreExample/Models/NonJsonApiResource.cs
new file mode 100644
index 0000000000..7f979f4cfb
--- /dev/null
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/NonJsonApiResource.cs
@@ -0,0 +1,7 @@
+namespace JsonApiDotNetCoreExample.Models
+{
+    public class NonJsonApiResource
+    {
+        public int Id { get; set; }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index 643df13bc3..73e355b2de 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -6,12 +6,50 @@
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
 
 namespace JsonApiDotNetCore.Builders
 {
+    public interface IContextGraphBuilder
+    {
+        /// <summary>
+        /// Construct the <see cref="ContextGraph"/>
+        /// </summary>
+        IContextGraph Build();
+
+        /// <summary>
+        /// Add a json:api resource
+        /// </summary>
+        /// <typeparam name="TResource">The resource model type</typeparam>
+        /// <param name="pluralizedTypeName">The pluralized name that should be exposed by the API</param>
+        IContextGraphBuilder AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>;
+
+        /// <summary>
+        /// Add a json:api resource
+        /// </summary>
+        /// <typeparam name="TResource">The resource model type</typeparam>
+        /// <typeparam name="TId">The resource model identifier type</typeparam>
+        /// <param name="pluralizedTypeName">The pluralized name that should be exposed by the API</param>
+        IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>;
+
+        /// <summary>
+        /// Add all the models that are part of the provided <see cref="DbContext" /> 
+        /// that also implement <see cref="IIdentifiable"/>
+        /// </summary>
+        /// <typeparam name="T">The <see cref="DbContext"/> implementation type.</typeparam>
+        IContextGraphBuilder AddDbContext<T>() where T : DbContext;
+
+        /// <summary>
+        /// Which links to include. Defaults to <see cref="Link.All"/>.
+        /// </summary>
+        Link DocumentLinks { get; set; }
+    }
+
     public class ContextGraphBuilder : IContextGraphBuilder
     {
         private List<ContextEntity> _entities = new List<ContextEntity>();
+        private List<ValidationResult> _validationResults = new List<ValidationResult>();
+
         private bool _usesDbContext;
         public Link DocumentLinks { get; set; } = Link.All;
 
@@ -20,7 +58,7 @@ public IContextGraph Build()
             // this must be done at build so that call order doesn't matter
             _entities.ForEach(e => e.Links = GetLinkFlags(e.EntityType));
 
-            var graph = new ContextGraph(_entities, _usesDbContext);
+            var graph = new ContextGraph(_entities, _usesDbContext, _validationResults);
 
             return graph;
         }
@@ -117,7 +155,10 @@ public IContextGraphBuilder AddDbContext<T>() where T : DbContext
 
                     AssertEntityIsNotAlreadyDefined(entityType);
 
-                    _entities.Add(GetEntity(GetResourceName(property), entityType, GetIdType(entityType)));
+                    var (isJsonApiResource, idType) = GetIdType(entityType);
+
+                    if (isJsonApiResource)
+                        _entities.Add(GetEntity(GetResourceName(property), entityType, idType));
                 }
             }
 
@@ -133,16 +174,18 @@ private string GetResourceName(PropertyInfo property)
             return ((ResourceAttribute)resourceAttribute).ResourceName;
         }
 
-        private Type GetIdType(Type resourceType)
+        private (bool isJsonApiResource, Type idType) GetIdType(Type resourceType)
         {
             var interfaces = resourceType.GetInterfaces();
             foreach (var type in interfaces)
             {
                 if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(IIdentifiable<>))
-                    return type.GetGenericArguments()[0];
+                    return (true, type.GetGenericArguments()[0]);
             }
 
-            throw new ArgumentException("Type does not implement 'IIdentifiable<TId>'", nameof(resourceType));
+            _validationResults.Add(new ValidationResult(LogLevel.Warning, $"{resourceType} does not implement 'IIdentifiable<>'. "));
+
+            return (false, null);
         }
 
         private void AssertEntityIsNotAlreadyDefined(Type entityType)
diff --git a/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
deleted file mode 100644
index 9f3c7bd1a8..0000000000
--- a/src/JsonApiDotNetCore/Builders/IContextGraphBuilder.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Models;
-using Microsoft.EntityFrameworkCore;
-
-namespace JsonApiDotNetCore.Builders
-{
-    public interface IContextGraphBuilder
-    {
-        Link DocumentLinks  { get; set; }
-        IContextGraph Build();
-        IContextGraphBuilder AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>;
-        IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>;
-        IContextGraphBuilder AddDbContext<T>() where T : DbContext;
-    }
-}
diff --git a/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs b/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs
index 651fbb44aa..996d7eb9de 100644
--- a/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs
@@ -1,7 +1,10 @@
+using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Middleware;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Logging;
 
 namespace JsonApiDotNetCore.Extensions
 {
@@ -9,21 +12,44 @@ namespace JsonApiDotNetCore.Extensions
     public static class IApplicationBuilderExtensions
     {
         public static IApplicationBuilder UseJsonApi(this IApplicationBuilder app, bool useMvc = true)
+        {
+            DisableDetailedErrorsIfProduction(app);
+            LogContextGraphValidations(app);
+
+            app.UseMiddleware<RequestMiddleware>();
+
+            if (useMvc)
+                app.UseMvc();
+
+            return app;
+        }
+
+        private static void DisableDetailedErrorsIfProduction(IApplicationBuilder app)
         {
             var environment = (IHostingEnvironment)app.ApplicationServices.GetService(typeof(IHostingEnvironment));
 
-            if(environment.IsProduction())
+            if (environment.IsProduction())
             {
                 JsonApiOptions.DisableErrorStackTraces = true;
                 JsonApiOptions.DisableErrorSource = true;
             }
+        }
 
-            app.UseMiddleware<RequestMiddleware>();
-
-            if (useMvc)
-                app.UseMvc();
+        private static void LogContextGraphValidations(IApplicationBuilder app)
+        {
+            var logger = app.ApplicationServices.GetService(typeof(ILogger<ContextGraphBuilder>)) as ILogger;
+            var contextGraph = app.ApplicationServices.GetService(typeof(IContextGraph)) as ContextGraph;
 
-            return app;
+            if (logger != null && contextGraph != null)
+            {
+                contextGraph.ValidationResults.ForEach((v) =>
+                    logger.Log(
+                        v.LogLevel,
+                        new EventId(),
+                        v.Message,
+                        exception: null,
+                        formatter: (m, e) => m));
+            }
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/ContextGraph.cs b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
index d21231f067..c27a01b7d8 100644
--- a/src/JsonApiDotNetCore/Internal/ContextGraph.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
@@ -4,25 +4,47 @@
 
 namespace JsonApiDotNetCore.Internal
 {
+    public interface IContextGraph
+    {
+        object GetRelationship<TParent>(TParent entity, string relationshipName);
+        string GetRelationshipName<TParent>(string relationshipName);
+        ContextEntity GetContextEntity(string dbSetName);
+        ContextEntity GetContextEntity(Type entityType);
+        bool UsesDbContext { get; }
+    }
+
     public class ContextGraph : IContextGraph
     {
-        private List<ContextEntity> _entities;
+        internal List<ContextEntity> Entities { get; }
+        internal List<ValidationResult> ValidationResults { get; }
 
         public ContextGraph() { }
 
         public ContextGraph(List<ContextEntity> entities, bool usesDbContext)
         {
-            _entities = entities;
+            Entities = entities;
+            UsesDbContext = usesDbContext;
+            ValidationResults = new List<ValidationResult>();
+        }
+
+        // eventually, this is the planned public constructor
+        // to avoid breaking changes, we will be leaving the original constructor in place
+        // until the context graph validation process is completed
+        // you can track progress on this issue here: https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/170
+        internal ContextGraph(List<ContextEntity> entities, bool usesDbContext, List<ValidationResult> validationResults)
+        {
+            Entities = entities;
             UsesDbContext = usesDbContext;
+            ValidationResults = validationResults;
         }
 
         public bool UsesDbContext { get; }
 
         public ContextEntity GetContextEntity(string entityName)
-            => _entities.SingleOrDefault(e => string.Equals(e.EntityName, entityName, StringComparison.OrdinalIgnoreCase));
+            => Entities.SingleOrDefault(e => string.Equals(e.EntityName, entityName, StringComparison.OrdinalIgnoreCase));
 
         public ContextEntity GetContextEntity(Type entityType)
-            => _entities.SingleOrDefault(e => e.EntityType == entityType);
+            => Entities.SingleOrDefault(e => e.EntityType == entityType);
 
         public object GetRelationship<TParent>(TParent entity, string relationshipName)
         {
@@ -41,7 +63,7 @@ public object GetRelationship<TParent>(TParent entity, string relationshipName)
         public string GetRelationshipName<TParent>(string relationshipName)
         {
             var entityType = typeof(TParent);
-            return _entities
+            return Entities
                 .SingleOrDefault(e => e.EntityType == entityType)
                 ?.Relationships
                 .SingleOrDefault(r => r.Is(relationshipName))
diff --git a/src/JsonApiDotNetCore/Internal/IContextGraph.cs b/src/JsonApiDotNetCore/Internal/IContextGraph.cs
deleted file mode 100644
index 5aa05bdacd..0000000000
--- a/src/JsonApiDotNetCore/Internal/IContextGraph.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-
-namespace JsonApiDotNetCore.Internal
-{
-    public interface IContextGraph
-    {
-        object GetRelationship<TParent>(TParent entity, string relationshipName);
-        string GetRelationshipName<TParent>(string relationshipName);
-        ContextEntity GetContextEntity(string dbSetName);
-        ContextEntity GetContextEntity(Type entityType);
-        bool UsesDbContext { get; }
-    }
-}
diff --git a/src/JsonApiDotNetCore/Internal/ValidationResults.cs b/src/JsonApiDotNetCore/Internal/ValidationResults.cs
new file mode 100644
index 0000000000..fbaa6eb462
--- /dev/null
+++ b/src/JsonApiDotNetCore/Internal/ValidationResults.cs
@@ -0,0 +1,16 @@
+using Microsoft.Extensions.Logging;
+
+namespace JsonApiDotNetCore.Internal
+{
+    internal class ValidationResult
+    {
+        public ValidationResult(LogLevel logLevel, string message)
+        {
+            LogLevel = logLevel;
+            Message = message;
+        }
+
+        public LogLevel LogLevel { get; set; }
+        public string Message { get; set; }
+    }
+}
diff --git a/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs b/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs
new file mode 100644
index 0000000000..ce8316b89d
--- /dev/null
+++ b/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs
@@ -0,0 +1,48 @@
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Internal;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using Xunit;
+
+namespace UnitTests.Internal
+{
+    public class ContextGraphBuilder_Tests
+    {
+        [Fact]
+        public void AddDbContext_Does_Not_Throw_If_Context_Contains_Members_That_DoNot_Implement_IIdentifiable()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+
+            // act
+            contextGraphBuilder.AddDbContext<TestContext>();
+            var contextGraph = contextGraphBuilder.Build() as ContextGraph;
+
+            // assert
+            Assert.Empty(contextGraph.Entities);
+        }
+
+        [Fact]
+        public void Adding_DbContext_Members_That_DoNot_Implement_IIdentifiable_Creates_Warning()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+
+            // act
+            contextGraphBuilder.AddDbContext<TestContext>();
+            var contextGraph = contextGraphBuilder.Build() as ContextGraph;
+
+            // assert
+            Assert.Equal(1, contextGraph.ValidationResults.Count);
+            Assert.Contains(contextGraph.ValidationResults, v => v.LogLevel == LogLevel.Warning);
+        }
+
+        private class Foo { }
+
+        private class TestContext : DbContext
+        {
+            public DbSet<Foo> Foos { get; set; }
+        }
+    }
+
+}

From 132050e96f53189dda2e7bad9b1ed593250a5b00 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 4 Apr 2018 15:51:18 -0500
Subject: [PATCH 118/227] chore(csproj): bump package version to 2.2.1

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 5aa6b6b897..c4b9a6d932 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.2.0</VersionPrefix>
+    <VersionPrefix>2.2.1</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From dd12e38af4317dd51b917b0d7886acd160797f13 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 7 Apr 2018 18:33:55 -0500
Subject: [PATCH 119/227] fix(Deserializer): remove dependency on
 GenericProcessorFactory

Rather than fetching data from the database during deserialization, we can set the relationships with instances that just carry the id. It will then be the responsibility of the repository to handle those relationships
---
 .../Extensions/TypeExtensions.cs              | 23 ++++++++++
 .../Serialization/JsonApiDeSerializer.cs      | 29 ++++++++----
 .../Extensions/TypeExtensions_Tests.cs        | 44 +++++++++++++++++++
 3 files changed, 88 insertions(+), 8 deletions(-)
 create mode 100644 test/UnitTests/Extensions/TypeExtensions_Tests.cs

diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
index ccc4619966..a78f545e81 100644
--- a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -31,5 +31,28 @@ public static Type GetElementType(this IEnumerable enumerable)
 
             return elementType;
         }
+
+        /// <summary>
+        /// Creates a List{TInterface} where TInterface is the generic for type specified by t
+        /// </summary>
+        public static List<TInterface> GetEmptyCollection<TInterface>(this Type t)
+        {
+            if (t == null) throw new ArgumentNullException(nameof(t));
+
+            var listType = typeof(List<>).MakeGenericType(t);
+            var list = (List<TInterface>)Activator.CreateInstance(listType);
+            return list;
+        }
+
+        /// <summary>
+        /// Creates a new instance of type t, casting it to the specified TInterface 
+        /// </summary>
+        public static TInterface New<TInterface>(this Type t)
+        {
+            if (t == null) throw new ArgumentNullException(nameof(t));
+
+            var instance = (TInterface)Activator.CreateInstance(t);
+            return instance;
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 649d6435ff..37e0314da6 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -9,20 +9,27 @@
 using JsonApiDotNetCore.Services;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
+using JsonApiDotNetCore.Extensions;
 
 namespace JsonApiDotNetCore.Serialization
 {
     public class JsonApiDeSerializer : IJsonApiDeSerializer
     {
         private readonly IJsonApiContext _jsonApiContext;
-        private readonly IGenericProcessorFactory _genericProcessorFactory;
 
+        [Obsolete(
+            "The deserializer no longer depends on the IGenericProcessorFactory",
+            error: false)]
         public JsonApiDeSerializer(
             IJsonApiContext jsonApiContext,
             IGenericProcessorFactory genericProcessorFactory)
         {
             _jsonApiContext = jsonApiContext;
-            _genericProcessorFactory = genericProcessorFactory;
+        }
+
+        public JsonApiDeSerializer(IJsonApiContext jsonApiContext)
+        {
+            _jsonApiContext = jsonApiContext;
         }
 
         public object Deserialize(string requestBody)
@@ -225,10 +232,11 @@ private object SetHasManyRelationship(object entity,
             ContextEntity contextEntity,
             Dictionary<string, RelationshipData> relationships)
         {
-            var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
+            // TODO: is this necessary? if not, remove
+            // var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
 
-            if (entityProperty == null)
-                throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain an relationsip named {attr.InternalRelationshipName}");
+            // if (entityProperty == null)
+            //     throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a relationsip named '{attr.InternalRelationshipName}'");
 
             var relationshipName = attr.PublicRelationshipName;
 
@@ -238,11 +246,16 @@ private object SetHasManyRelationship(object entity,
 
                 if (data == null) return entity;
 
-                var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(typeof(GenericProcessor<>), attr.Type);
+                var resourceRelationships = attr.Type.GetEmptyCollection<IIdentifiable>();
 
-                var ids = relationshipData.ManyData.Select(r => r.Id);
+                var relationshipShells = relationshipData.ManyData.Select(r =>
+                {
+                    var instance = attr.Type.New<IIdentifiable>();
+                    instance.StringId = r.Id;
+                    return instance;
+                });
 
-                genericProcessor.SetRelationships(entity, attr, ids);
+                attr.SetValue(entity, relationshipShells);
             }
 
             return entity;
diff --git a/test/UnitTests/Extensions/TypeExtensions_Tests.cs b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
new file mode 100644
index 0000000000..92534eef5d
--- /dev/null
+++ b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
@@ -0,0 +1,44 @@
+using JsonApiDotNetCore.Models;
+using Xunit;
+using JsonApiDotNetCore.Extensions;
+using System.Collections.Generic;
+
+namespace UnitTests.Extensions
+{
+    public class TypeExtensions_Tests
+    {
+        [Fact]
+        public void GetCollection_Creates_List_If_T_Implements_Interface()
+        {
+            // arrange
+            var type = typeof(Model);
+
+            // act
+            var collection = type.GetEmptyCollection<IIdentifiable>();
+
+            // assert
+            Assert.NotNull(collection);
+            Assert.Empty(collection);
+            Assert.IsType<List<Model>>(collection);
+        }
+
+        [Fact]
+        public void New_Creates_An_Instance_If_T_Implements_Interface()
+        {
+            // arrange
+            var type = typeof(Model);
+
+            // act
+            var instance = type.New<IIdentifiable>();
+
+            // assert
+            Assert.NotNull(instance);
+            Assert.IsType<Model>(instance);
+        }
+
+        private class Model : IIdentifiable
+        {
+            public string StringId { get; set; }
+        }
+    }
+}

From e5a0f6d05452fc78fe6d82268cb7e46fee8c1680 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 7 Apr 2018 19:08:18 -0500
Subject: [PATCH 120/227] fix(typeExtensions): cast to IEnumerable using
 covariance

---
 src/JsonApiDotNetCore/Extensions/TypeExtensions.cs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
index a78f545e81..efe29620f8 100644
--- a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -35,12 +35,12 @@ public static Type GetElementType(this IEnumerable enumerable)
         /// <summary>
         /// Creates a List{TInterface} where TInterface is the generic for type specified by t
         /// </summary>
-        public static List<TInterface> GetEmptyCollection<TInterface>(this Type t)
+        public static IEnumerable<TInterface> GetEmptyCollection<TInterface>(this Type t)
         {
             if (t == null) throw new ArgumentNullException(nameof(t));
 
             var listType = typeof(List<>).MakeGenericType(t);
-            var list = (List<TInterface>)Activator.CreateInstance(listType);
+            var list = (IEnumerable<TInterface>)Activator.CreateInstance(listType);
             return list;
         }
 

From 79084ba162bee0c69f55390cf5339898d1b5b94f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 7 Apr 2018 20:57:26 -0500
Subject: [PATCH 121/227] fix(Deserializer): properly convert collection type
 when setting it on the model

---
 src/JsonApiDotNetCore/Extensions/TypeExtensions.cs     |  4 ++--
 src/JsonApiDotNetCore/Internal/TypeHelper.cs           | 10 ++++++++++
 src/JsonApiDotNetCore/Models/HasManyAttribute.cs       |  2 +-
 .../Serialization/JsonApiDeSerializer.cs               | 10 ++++++----
 test/UnitTests/Extensions/TypeExtensions_Tests.cs      |  6 +++---
 5 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
index efe29620f8..8cc7c0dffe 100644
--- a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -35,12 +35,12 @@ public static Type GetElementType(this IEnumerable enumerable)
         /// <summary>
         /// Creates a List{TInterface} where TInterface is the generic for type specified by t
         /// </summary>
-        public static IEnumerable<TInterface> GetEmptyCollection<TInterface>(this Type t)
+        public static IEnumerable GetEmptyCollection(this Type t)
         {
             if (t == null) throw new ArgumentNullException(nameof(t));
 
             var listType = typeof(List<>).MakeGenericType(t);
-            var list = (IEnumerable<TInterface>)Activator.CreateInstance(listType);
+            var list = (IEnumerable)Activator.CreateInstance(listType);
             return list;
         }
 
diff --git a/src/JsonApiDotNetCore/Internal/TypeHelper.cs b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
index cc64b398dd..2493bfab4a 100644
--- a/src/JsonApiDotNetCore/Internal/TypeHelper.cs
+++ b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
@@ -1,10 +1,20 @@
 using System;
+using System.Collections;
+using System.Collections.Generic;
 using System.Reflection;
 
 namespace JsonApiDotNetCore.Internal
 {
     public static class TypeHelper
     {
+        public static IList ConvertCollection(IEnumerable<object> collection, Type targetType)
+        {
+            var list = Activator.CreateInstance(typeof(List<>).MakeGenericType(targetType)) as IList;
+            foreach(var item in collection)
+                list.Add(ConvertType(item, targetType));
+            return list;
+        }
+
         public static object ConvertType(object value, Type type)
         {
             if (value == null)
diff --git a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
index b4fd1b42ec..7d2fa87ec4 100644
--- a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
@@ -12,7 +12,7 @@ public override void SetValue(object entity, object newValue)
                 .GetType()
                 .GetProperty(InternalRelationshipName);
             
-            propertyInfo.SetValue(entity, newValue);        
+            propertyInfo.SetValue(entity, newValue);
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 37e0314da6..70246cb351 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models;
@@ -9,7 +10,6 @@
 using JsonApiDotNetCore.Services;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
-using JsonApiDotNetCore.Extensions;
 
 namespace JsonApiDotNetCore.Serialization
 {
@@ -246,8 +246,6 @@ private object SetHasManyRelationship(object entity,
 
                 if (data == null) return entity;
 
-                var resourceRelationships = attr.Type.GetEmptyCollection<IIdentifiable>();
-
                 var relationshipShells = relationshipData.ManyData.Select(r =>
                 {
                     var instance = attr.Type.New<IIdentifiable>();
@@ -255,7 +253,11 @@ private object SetHasManyRelationship(object entity,
                     return instance;
                 });
 
-                attr.SetValue(entity, relationshipShells);
+                var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
+
+                // var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
+
+                attr.SetValue(entity, convertedCollection);
             }
 
             return entity;
diff --git a/test/UnitTests/Extensions/TypeExtensions_Tests.cs b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
index 92534eef5d..f59fa37be0 100644
--- a/test/UnitTests/Extensions/TypeExtensions_Tests.cs
+++ b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
@@ -1,7 +1,7 @@
+using System.Collections.Generic;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Models;
 using Xunit;
-using JsonApiDotNetCore.Extensions;
-using System.Collections.Generic;
 
 namespace UnitTests.Extensions
 {
@@ -14,7 +14,7 @@ public void GetCollection_Creates_List_If_T_Implements_Interface()
             var type = typeof(Model);
 
             // act
-            var collection = type.GetEmptyCollection<IIdentifiable>();
+            var collection = type.GetEmptyCollection();
 
             // assert
             Assert.NotNull(collection);

From be33bac61e45b29c53ceb8b2fe0b88201f903b33 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 8 Apr 2018 07:10:26 -0500
Subject: [PATCH 122/227] set new HasManyRelationships with
 EntityState.Unchanged

---
 .../Data/DefaultEntityRepository.cs           | 19 +++++++
 .../Data/IEntityRepository.cs                 |  4 --
 .../Extensions/DbContextExtensions.cs         | 16 ++----
 .../Request/HasManyRelationshipPointers.cs    | 49 +++++++++++++++++++
 .../Serialization/JsonApiDeSerializer.cs      | 10 +---
 .../Services/IJsonApiContext.cs               |  2 +
 .../Services/JsonApiContext.cs                |  3 +-
 7 files changed, 78 insertions(+), 25 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index e551bb9491..c4ebf2f738 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -85,10 +85,29 @@ public virtual async Task<TEntity> GetAndIncludeAsync(TId id, string relationshi
         public virtual async Task<TEntity> CreateAsync(TEntity entity)
         {
             _dbSet.Add(entity);
+
+            DetachHasManyPointers();
+
             await _context.SaveChangesAsync();
             return entity;
         }
 
+        /// <summary>
+        /// This is used to allow creation of HasMany relationships when the
+        /// dependent side of the relationship already exists.
+        /// </summary>
+        private void DetachHasManyPointers()
+        {
+            var relationships = _jsonApiContext.HasManyRelationshipPointers.Get();
+            foreach(var relationship in relationships)
+            {
+                foreach(var pointer in relationship.Value)
+                {
+                    _context.Entry(pointer).State = EntityState.Unchanged;
+                }
+            }
+        }
+
         public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
         {
             var oldEntity = await GetAsync(id);
diff --git a/src/JsonApiDotNetCore/Data/IEntityRepository.cs b/src/JsonApiDotNetCore/Data/IEntityRepository.cs
index 4c35d6ea3f..e8bb68ef90 100644
--- a/src/JsonApiDotNetCore/Data/IEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/IEntityRepository.cs
@@ -1,7 +1,3 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
 
 namespace JsonApiDotNetCore.Data
diff --git a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
index 2606342e29..3cb5ccc359 100644
--- a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
@@ -1,20 +1,12 @@
-using Microsoft.EntityFrameworkCore;
 using System;
+using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Extensions
 {
     public static class DbContextExtensions
     {
-        public static DbSet<T> GetDbSet<T>(this DbContext context) where T : class
-        {
-            var contextProperties = context.GetType().GetProperties();
-            foreach(var property in contextProperties)
-            {
-                if (property.PropertyType == typeof(DbSet<T>))
-                    return (DbSet<T>)property.GetValue(context);
-            }
-
-            throw new ArgumentException($"DbSet of type {typeof(T).FullName} not found on the DbContext", nameof(T));
-        }
+        [Obsolete("This is no longer required since the introduction of context.Set<T>", error: false)]
+        public static DbSet<T> GetDbSet<T>(this DbContext context) where T : class 
+            => context.Set<T>();
     }
 }
diff --git a/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs b/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
new file mode 100644
index 0000000000..721274e3d6
--- /dev/null
+++ b/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace JsonApiDotNetCore.Request
+{
+    /// <summary>
+    /// Stores information to set relationships for the request resource. 
+    /// These relationships must already exist and should not be re-created.
+    /// 
+    /// The expected use case is POST-ing or PATCH-ing 
+    /// an entity with HasMany relaitonships:
+    /// <code>
+    /// {
+    ///    "data": {
+    ///      "type": "photos",
+    ///      "attributes": {
+    ///        "title": "Ember Hamster",
+    ///        "src": "http://example.com/images/productivity.png"
+    ///      },
+    ///      "relationships": {
+    ///        "tags": {
+    ///          "data": [
+    ///            { "type": "tags", "id": "2" },
+    ///            { "type": "tags", "id": "3" }
+    ///          ]
+    ///        }
+    ///      }
+    ///    }
+    ///  }
+    /// </code>
+    /// </summary>
+    public class HasManyRelationshipPointers
+    {
+        private Dictionary<Type, IList> _hasManyRelationships = new Dictionary<Type, IList>();
+
+        /// <summary>
+        /// Add the relationship to the list of relationships that should be 
+        /// set in the repository layer.
+        /// </summary>
+        public void Add(Type dependentType, IList entities)
+            => _hasManyRelationships[dependentType] = entities;
+
+        /// <summary>
+        /// Get all the models that should be associated
+        /// </summary>
+        public Dictionary<Type, IList> Get() => _hasManyRelationships;
+    }
+}
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 70246cb351..9723f79dac 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -232,12 +232,6 @@ private object SetHasManyRelationship(object entity,
             ContextEntity contextEntity,
             Dictionary<string, RelationshipData> relationships)
         {
-            // TODO: is this necessary? if not, remove
-            // var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
-
-            // if (entityProperty == null)
-            //     throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a relationsip named '{attr.InternalRelationshipName}'");
-
             var relationshipName = attr.PublicRelationshipName;
 
             if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
@@ -255,9 +249,9 @@ private object SetHasManyRelationship(object entity,
 
                 var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
 
-                // var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
-
                 attr.SetValue(entity, convertedCollection);
+
+                _jsonApiContext.HasManyRelationshipPointers.Add(attr.Type, convertedCollection);
             }
 
             return entity;
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index a73f0eb53a..132630446d 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -6,6 +6,7 @@
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Request;
 
 namespace JsonApiDotNetCore.Services
 {
@@ -28,6 +29,7 @@ public interface IJsonApiContext
         Type ControllerType { get; set; }
         Dictionary<string, object> DocumentMeta { get; set; }
         bool IsBulkOperationRequest { get; set; }
+        HasManyRelationshipPointers HasManyRelationshipPointers { get; }
 
         TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
     }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 1ebf5aeea1..a8bd9fe5de 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -1,12 +1,12 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Request;
 using Microsoft.AspNetCore.Http;
 
 namespace JsonApiDotNetCore.Services
@@ -52,6 +52,7 @@ public JsonApiContext(
         public Type ControllerType { get; set; }
         public Dictionary<string, object> DocumentMeta { get; set; }
         public bool IsBulkOperationRequest { get; set; }
+        public HasManyRelationshipPointers HasManyRelationshipPointers { get; } = new HasManyRelationshipPointers();
 
         public IJsonApiContext ApplyContext<T>(object controller)
         {

From af0e77f638744e2f5a880bb58a76a496bc098e09 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 8 Apr 2018 07:26:15 -0500
Subject: [PATCH 123/227] ensure pointers are attached prior to adding the
 entity

---
 src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index c4ebf2f738..3c85bdae80 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -84,10 +84,9 @@ public virtual async Task<TEntity> GetAndIncludeAsync(TId id, string relationshi
 
         public virtual async Task<TEntity> CreateAsync(TEntity entity)
         {
+            AttachHasManyPointers();
             _dbSet.Add(entity);
 
-            DetachHasManyPointers();
-
             await _context.SaveChangesAsync();
             return entity;
         }
@@ -96,7 +95,7 @@ public virtual async Task<TEntity> CreateAsync(TEntity entity)
         /// This is used to allow creation of HasMany relationships when the
         /// dependent side of the relationship already exists.
         /// </summary>
-        private void DetachHasManyPointers()
+        private void AttachHasManyPointers()
         {
             var relationships = _jsonApiContext.HasManyRelationshipPointers.Get();
             foreach(var relationship in relationships)

From 11dafb92b4288ed09e2f4fa4afb496816ded3d6c Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 8 Apr 2018 15:33:58 -0500
Subject: [PATCH 124/227] fix tests

---
 .../Unit => UnitTests}/Builders/MetaBuilderTests.cs        | 6 +++---
 .../Extensions/IServiceCollectionExtensionsTests.cs        | 7 +++----
 .../Unit => UnitTests}/Models/AttributesEqualsTests.cs     | 2 +-
 test/UnitTests/UnitTests.csproj                            | 1 +
 4 files changed, 8 insertions(+), 8 deletions(-)
 rename test/{JsonApiDotNetCoreExampleTests/Unit => UnitTests}/Builders/MetaBuilderTests.cs (97%)
 rename test/{JsonApiDotNetCoreExampleTests/Unit => UnitTests}/Extensions/IServiceCollectionExtensionsTests.cs (92%)
 rename test/{JsonApiDotNetCoreExampleTests/Unit => UnitTests}/Models/AttributesEqualsTests.cs (97%)

diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs b/test/UnitTests/Builders/MetaBuilderTests.cs
similarity index 97%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs
rename to test/UnitTests/Builders/MetaBuilderTests.cs
index 5cd0b765de..0b784ef5b7 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs
+++ b/test/UnitTests/Builders/MetaBuilderTests.cs
@@ -1,8 +1,8 @@
-using Xunit;
-using JsonApiDotNetCore.Builders;
 using System.Collections.Generic;
+using JsonApiDotNetCore.Builders;
+using Xunit;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Builders
+namespace UnitTests.Builders
 {
     public class MetaBuilderTests
     {
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
similarity index 92%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
rename to test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
index f6772fa22b..4fe2f09ff1 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
+++ b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
@@ -10,12 +10,11 @@
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Caching.Memory;
 using Microsoft.Extensions.DependencyInjection;
-using UnitTests;
 using Xunit;
+using Microsoft.EntityFrameworkCore;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Extensions
+namespace UnitTests.Extensions
 {
     public class IServiceCollectionExtensionsTests
     {
@@ -28,7 +27,7 @@ public void AddJsonApiInternals_Adds_All_Required_Services()
 
             services.AddDbContext<AppDbContext>(options =>
             {
-                options.UseMemoryCache(new MemoryCache(new MemoryCacheOptions()));
+                options.UseInMemoryDatabase();
             }, ServiceLifetime.Transient);
 
             // act
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs b/test/UnitTests/Models/AttributesEqualsTests.cs
similarity index 97%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs
rename to test/UnitTests/Models/AttributesEqualsTests.cs
index 107dd1d593..0b989169ef 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs
+++ b/test/UnitTests/Models/AttributesEqualsTests.cs
@@ -1,7 +1,7 @@
 using JsonApiDotNetCore.Models;
 using Xunit;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Models
+namespace UnitTests.Models
 {
     public class AttributesEqualsTests
     {
diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj
index 14a0d30e33..a6ed346e7d 100644
--- a/test/UnitTests/UnitTests.csproj
+++ b/test/UnitTests/UnitTests.csproj
@@ -12,5 +12,6 @@
     <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
     <PackageReference Include="xunit" Version="$(XUnitVersion)" />
     <PackageReference Include="Moq" Version="$(MoqVersion)" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.2" />
   </ItemGroup>
 </Project>

From 621091985edf4e5d0a32df59104f2db2c2af33d3 Mon Sep 17 00:00:00 2001
From: Corey Floyd <fourfloyds@gmail.com>
Date: Thu, 19 Apr 2018 22:56:53 -0500
Subject: [PATCH 125/227] #162 Adds new boolean value for 'canInclude' to
 ResourceAttribute. Updates DefaultEntityRepository to check this value when
 including relationship entities and to throw if set to false.

---
 .../Data/DefaultEntityRepository.cs               | 15 +++++++++++----
 src/JsonApiDotNetCore/Models/HasManyAttribute.cs  |  4 ++--
 src/JsonApiDotNetCore/Models/HasOneAttribute.cs   |  4 ++--
 .../Models/RelationshipAttribute.cs               |  7 ++++---
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index e551bb9491..b6bcda29b3 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -131,11 +131,18 @@ public virtual IQueryable<TEntity> Include(IQueryable<TEntity> entities, string
         {
             var entity = _jsonApiContext.RequestEntity;
             var relationship = entity.Relationships.FirstOrDefault(r => r.PublicRelationshipName == relationshipName);
-            if (relationship != null)
-                return entities.Include(relationship.InternalRelationshipName);
+            if (relationship == null) 
+            {
+                throw new JsonApiException(400, $"Invalid relationship {relationshipName} on {entity.EntityName}",
+                    $"{entity.EntityName} does not have a relationship named {relationshipName}");
+            }
+
+            if (!relationship.CanInclude)
+            {
+                throw new JsonApiException(400, $"Including the relationship {relationshipName} on {entity.EntityName} is not allowed");
+            }
+            return entities.Include(relationship.InternalRelationshipName);
 
-            throw new JsonApiException(400, $"Invalid relationship {relationshipName} on {entity.EntityName}",
-                $"{entity.EntityName} does not have a relationship named {relationshipName}");
         }
 
         public virtual async Task<IEnumerable<TEntity>> PageAsync(IQueryable<TEntity> entities, int pageSize, int pageNumber)
diff --git a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
index b4fd1b42ec..4519dc8cb6 100644
--- a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
@@ -2,8 +2,8 @@ namespace JsonApiDotNetCore.Models
 {
     public class HasManyAttribute : RelationshipAttribute
     {
-        public HasManyAttribute(string publicName, Link documentLinks = Link.All)
-        : base(publicName, documentLinks)
+        public HasManyAttribute(string publicName, Link documentLinks = Link.All, bool canInclude = true)
+        : base(publicName, documentLinks, canInclude)
         { }
 
         public override void SetValue(object entity, object newValue)
diff --git a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
index 0dd20e73e7..f863c8819b 100644
--- a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
@@ -2,8 +2,8 @@ namespace JsonApiDotNetCore.Models
 {
     public class HasOneAttribute : RelationshipAttribute
     {
-        public HasOneAttribute(string publicName, Link documentLinks = Link.All)
-        : base(publicName, documentLinks)
+        public HasOneAttribute(string publicName, Link documentLinks = Link.All, bool canInclude = true)
+        : base(publicName, documentLinks, canInclude)
         { }
 
         public override void SetValue(object entity, object newValue)
diff --git a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
index 0dbe6a4670..2781ecfb53 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
@@ -4,10 +4,11 @@ namespace JsonApiDotNetCore.Models
 {
     public abstract class RelationshipAttribute : Attribute
     {
-        protected RelationshipAttribute(string publicName, Link documentLinks)
+        protected RelationshipAttribute(string publicName, Link documentLinks, bool canInclude)
         {
             PublicRelationshipName = publicName;
             DocumentLinks = documentLinks;
+            CanInclude = canInclude;
         }
 
         public string PublicRelationshipName { get; }
@@ -16,6 +17,7 @@ protected RelationshipAttribute(string publicName, Link documentLinks)
         public bool IsHasMany => GetType() == typeof(HasManyAttribute);
         public bool IsHasOne => GetType() == typeof(HasOneAttribute);
         public Link DocumentLinks { get; } = Link.All;
+        public bool CanInclude { get; }
 
         public abstract void SetValue(object entity, object newValue);
 
@@ -26,8 +28,7 @@ public override string ToString()
 
         public override bool Equals(object obj)
         {
-            var attr = obj as RelationshipAttribute;
-            if (attr == null)
+            if (!(obj is RelationshipAttribute attr))
             {
                 return false;
             }

From 0723567a8cd2771279ce5502fdb782c27bb0bfa5 Mon Sep 17 00:00:00 2001
From: Corey Floyd <fourfloyds@gmail.com>
Date: Thu, 19 Apr 2018 22:59:05 -0500
Subject: [PATCH 126/227] #162 Adds unit test to test the new canInclude
 ResourceAttribute property.

---
 .../JsonApiDotNetCoreExample/Models/Person.cs |  3 +++
 .../Acceptance/Spec/DocumentTests/Included.cs | 24 +++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs
index 8acf87c405..5aa7c83c12 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs
@@ -20,6 +20,9 @@ public class Person : Identifiable, IHasMeta
         
         [HasMany("todo-collections")]
         public virtual List<TodoItemCollection> TodoItemCollections { get; set; }
+        
+        [HasOne("unincludeable-item", Link.All, false)]
+        public virtual TodoItem UnIncludeableItem { get; set; }
 
         public Dictionary<string, object> GetMeta(IJsonApiContext context)
         {
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
index a9aa9c4e67..343526f7d8 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
@@ -335,5 +335,29 @@ public async Task Request_ToIncludeDeeplyNestedRelationships_Returns_400()
             // assert
             Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
         }
+
+        [Fact]
+        public async Task Request_ToIncludeRelationshipMarkedCanIncludeFalse_Returns_400()
+        {
+            // arrange
+            var person = _context.People.First();
+
+            var builder = new WebHostBuilder()
+                .UseStartup<Startup>();
+
+            var httpMethod = new HttpMethod("GET");
+
+            var route = $"/api/v1/people/{person.Id}?include=unincludeable-item";
+
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // act
+            var response = await client.SendAsync(request);
+
+            // assert
+            Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+        }
     }
 }

From 41b0415a24af79f54eef6453ca51e9b13df86bdb Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 21 Apr 2018 17:54:56 -0500
Subject: [PATCH 127/227] make private service methods protected virtual

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj          | 4 ++--
 src/JsonApiDotNetCore/Services/EntityResourceService.cs | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index c4b9a6d932..8cd4435ad8 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.2.1</VersionPrefix>
+    <VersionPrefix>2.2.2</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>
@@ -35,4 +35,4 @@
     <PackageReference Include="docfx.console" Version="2.33.0" />
   </ItemGroup>
 
-</Project>
\ No newline at end of file
+</Project>
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index 91eabb9cfd..bc7a2adb52 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -146,7 +146,7 @@ public virtual async Task<bool> DeleteAsync(TId id)
             return await _entities.DeleteAsync(id);
         }
 
-        private IQueryable<T> ApplySortAndFilterQuery(IQueryable<T> entities)
+        protected virtual IQueryable<T> ApplySortAndFilterQuery(IQueryable<T> entities)
         {
             var query = _jsonApiContext.QuerySet;
 
@@ -163,7 +163,7 @@ private IQueryable<T> ApplySortAndFilterQuery(IQueryable<T> entities)
             return entities;
         }
 
-        private async Task<IEnumerable<T>> ApplyPageQueryAsync(IQueryable<T> entities)
+        protected virtual async Task<IEnumerable<T>> ApplyPageQueryAsync(IQueryable<T> entities)
         {
             var pageManager = _jsonApiContext.PageManager;
             if (!pageManager.IsPaginated)
@@ -174,7 +174,7 @@ private async Task<IEnumerable<T>> ApplyPageQueryAsync(IQueryable<T> entities)
             return await _entities.PageAsync(entities, pageManager.PageSize, pageManager.CurrentPage);
         }
 
-        private IQueryable<T> IncludeRelationships(IQueryable<T> entities, List<string> relationships)
+        protected virtual IQueryable<T> IncludeRelationships(IQueryable<T> entities, List<string> relationships)
         {
             _jsonApiContext.IncludedRelationships = relationships;
 

From 0cfa4e63fd19341220c3dbd3efe5ec4493082507 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 21 Apr 2018 18:05:11 -0500
Subject: [PATCH 128/227] allow custom attribute filters

---
 .../Extensions/IQueryableExtensions.cs                 |  2 +-
 .../Internal/Query/AttrFilterQuery.cs                  | 10 +++++++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index 73e3a14a3e..4d7be752e3 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -90,7 +90,7 @@ public static IQueryable<TSource> Filter<TSource>(this IQueryable<TSource> sourc
 
         public static IQueryable<TSource> Filter<TSource>(this IQueryable<TSource> source, AttrFilterQuery filterQuery)
         {
-            if (filterQuery == null)
+            if (filterQuery == null || filterQuery.IsAttribute == false)
                 return source;
 
             var concreteType = typeof(TSource);
diff --git a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
index 59bb3f0f83..c8dee16828 100644
--- a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
@@ -18,7 +18,9 @@ public AttrFilterQuery(
             var attribute = GetAttribute(filterQuery.Attribute);
 
             if (attribute == null)
-                throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
+                return; // we don't want to throw...we should allow custom filter implementations
+
+            IsAttribute = true;
 
             if (attribute.IsFilterable == false)
                 throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'.");
@@ -32,6 +34,12 @@ public AttrFilterQuery(
         public string PropertyValue { get; }
         public FilterOperations FilterOperation { get; }
 
+        /// <summary>
+        /// Whether or not the filter is an actual attribute on the model.
+        /// We use this to allow custom filters that have to be handled by the application.
+        /// </summary>
+        internal bool IsAttribute { get; set; }
+
         private AttrAttribute GetAttribute(string attribute) =>
             _jsonApiContext.RequestEntity.Attributes.FirstOrDefault(attr => attr.Is(attribute));
     }

From 4ec71e0293ac9f64d4ffac47cfaff7a87ccc7648 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 21 Apr 2018 18:26:05 -0500
Subject: [PATCH 129/227] add ctor without logger factory

---
 src/JsonApiDotNetCore/Controllers/JsonApiController.cs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiController.cs
index 97350127ba..929e76e5aa 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiController.cs
@@ -17,6 +17,12 @@ public JsonApiController(
             : base(jsonApiContext, resourceService, loggerFactory)
         { }
 
+        public JsonApiController(
+            IJsonApiContext jsonApiContext,
+            IResourceService<T, int> resourceService)
+            : base(jsonApiContext, resourceService)
+        { }
+
         public JsonApiController(
             IJsonApiContext jsonApiContext,
             IGetAllService<T, int> getAll = null,

From 8c06ae39b2d59cb66838ad6af069b9b592a93bc2 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 21 Apr 2018 18:05:11 -0500
Subject: [PATCH 130/227] Revert "allow custom attribute filters"

This reverts commit 1c80eb72a524a806d0fdc49b9e7aff34b681c86a.
---
 .../Extensions/IQueryableExtensions.cs                 |  2 +-
 .../Internal/Query/AttrFilterQuery.cs                  | 10 +---------
 2 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index 4d7be752e3..73e3a14a3e 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -90,7 +90,7 @@ public static IQueryable<TSource> Filter<TSource>(this IQueryable<TSource> sourc
 
         public static IQueryable<TSource> Filter<TSource>(this IQueryable<TSource> source, AttrFilterQuery filterQuery)
         {
-            if (filterQuery == null || filterQuery.IsAttribute == false)
+            if (filterQuery == null)
                 return source;
 
             var concreteType = typeof(TSource);
diff --git a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
index c8dee16828..59bb3f0f83 100644
--- a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
@@ -18,9 +18,7 @@ public AttrFilterQuery(
             var attribute = GetAttribute(filterQuery.Attribute);
 
             if (attribute == null)
-                return; // we don't want to throw...we should allow custom filter implementations
-
-            IsAttribute = true;
+                throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
 
             if (attribute.IsFilterable == false)
                 throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'.");
@@ -34,12 +32,6 @@ public AttrFilterQuery(
         public string PropertyValue { get; }
         public FilterOperations FilterOperation { get; }
 
-        /// <summary>
-        /// Whether or not the filter is an actual attribute on the model.
-        /// We use this to allow custom filters that have to be handled by the application.
-        /// </summary>
-        internal bool IsAttribute { get; set; }
-
         private AttrAttribute GetAttribute(string attribute) =>
             _jsonApiContext.RequestEntity.Attributes.FirstOrDefault(attr => attr.Is(attribute));
     }

From 6726794a7688066ee9c9c9fc6e29eaea658faf15 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Sun, 22 Apr 2018 07:40:44 -0500
Subject: [PATCH 131/227] fix documentation link

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index c09fe884b6..ae66e3a07c 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ See the [examples](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/mas
 
 ## Installation And Usage
 
-See [the documentation](https://json-api-dotnet.github.io/JsonApiDotNetCore/) for detailed usage. 
+See [the documentation](https://json-api-dotnet.github.io/#/) for detailed usage. 
 
 ### Models
 

From bf79a20bc730e883784ed94ebe484f07c58cb2eb Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 22 Apr 2018 07:43:38 -0500
Subject: [PATCH 132/227] chore(docs): removed obsolete docs

---
 couscous.yml                   | 116 --------------------------
 docs/ContextGraph.md           |  58 -------------
 docs/Controllers.md            |  93 ---------------------
 docs/CustomQueryFormat.md      |  13 ---
 docs/EntityRepositories.md     |  44 ----------
 docs/Errors.md                 |  38 ---------
 docs/Filtering.md              |  50 ------------
 docs/IncludingRelationships.md |  54 -------------
 docs/Index.md                  |   7 --
 docs/Installation.md           |  29 -------
 docs/Layers.md                 |  57 -------------
 docs/Meta.md                   |  29 -------
 docs/Middleware.md             |  20 -----
 docs/Models.md                 | 106 ------------------------
 docs/Operations.md             |  33 --------
 docs/Options.md                | 111 -------------------------
 docs/Pagination.md             |  23 ------
 docs/ResourceServices.md       | 126 -----------------------------
 docs/Routing.md                |  65 ---------------
 docs/Sorting.md                |  12 ---
 docs/SparseFieldsets.md        |  20 -----
 docs/Usage.md                  | 144 ---------------------------------
 docs/service_table.png         | Bin 169430 -> 0 bytes
 23 files changed, 1248 deletions(-)
 delete mode 100644 couscous.yml
 delete mode 100644 docs/ContextGraph.md
 delete mode 100644 docs/Controllers.md
 delete mode 100644 docs/CustomQueryFormat.md
 delete mode 100644 docs/EntityRepositories.md
 delete mode 100644 docs/Errors.md
 delete mode 100644 docs/Filtering.md
 delete mode 100644 docs/IncludingRelationships.md
 delete mode 100644 docs/Index.md
 delete mode 100644 docs/Installation.md
 delete mode 100644 docs/Layers.md
 delete mode 100644 docs/Meta.md
 delete mode 100644 docs/Middleware.md
 delete mode 100644 docs/Models.md
 delete mode 100644 docs/Operations.md
 delete mode 100644 docs/Options.md
 delete mode 100644 docs/Pagination.md
 delete mode 100644 docs/ResourceServices.md
 delete mode 100644 docs/Routing.md
 delete mode 100644 docs/Sorting.md
 delete mode 100644 docs/SparseFieldsets.md
 delete mode 100644 docs/Usage.md
 delete mode 100644 docs/service_table.png

diff --git a/couscous.yml b/couscous.yml
deleted file mode 100644
index 2acaad12d7..0000000000
--- a/couscous.yml
+++ /dev/null
@@ -1,116 +0,0 @@
-template:
-    # Name of the directory containing the website template (default is "website")
-    # directory: docs/Template-Dark
-    # Or if you are using a remote template, you can set the Git URL
-    url: https://github.com/jaredcnance/Template-Dark.git
-    # Name of the index file (default is "README.md")
-    index: index.md
-
-# List of directories to include in the processing (by default it's empty, so all markdown files are parsed)
-# Paths are relative to the optional source path given when generating the website, repository root by default
-include:
-    - docs
-
-# List of directories to exclude from the processing (default contains "vendor" and "website")
-# Paths are relative to the optional include paths given when generating the website, repository root by default
-exclude:
-    # This special entry will ask Couscous to read the exluded directories from your ".gitignore"  file
-    - %gitignore%
-
-# scripts:
-    # Scripts to execute before generating the website
-    # before:
-    #    - cp bin/couscous.phar website/
-    # Scripts to execute after generating the website
-    # after:
-    #    - rm website/couscous.phar
-
-# Set this variable to use a Custom Domain
-# The content of this variable will be directly inserted into the CNAME file
-# cname: docs.yourdomain.com
-
-# Set the target branch in which to deploy the generated website
-branch: gh-pages
-
-# Base URL of the published website (no "/" at the end!)
-# You are advised to set and use this variable to write your links in the HTML layouts
-baseUrl: https://json-api-dotnet.github.io/JsonApiDotNetCore/
-github:
-    user: research-institute
-    repo: json-api-dotnet-core
-
-title: JSONAPI .Net Core
-subTitle: killing boilerplate in dotnet web APIs
-
-# The left menu bar
-menu:
-    sections:
-        intro:
-            name: Getting Started
-            items:
-                about:
-                    text: About
-                    relativeUrl: index.html
-                installation:
-                    text: Installation
-                    relativeUrl: installation.html
-                usage:
-                    text: Step by Step
-                    relativeUrl: usage.html
-        usage:
-            name: Usage
-            items:
-                models:
-                    text: Models
-                    relativeUrl: models.html
-                contextgraph:
-                    text: Context Graph
-                    relativeUrl: contextgraph.html
-                meta:
-                    text: Meta
-                    relativeUrl: meta.html
-                options:
-                    text: Global Options
-                    relativeUrl: options.html
-                errors:
-                    text: Custom Errors
-                    relativeUrl: errors.html
-                filtering:
-                    text: Filtering
-                    relativeUrl: filtering.html
-                includingrelationships:
-                    text: Including Relationships
-                    relativeUrl: includingrelationships.html
-                pagination:
-                    text: Pagination
-                    relativeUrl: pagination.html
-                routing:
-                    text: Routing
-                    relativeUrl: routing.html
-                sorting:
-                    text: Sorting
-                    relativeUrl: sorting.html
-                sparsefields:
-                    text: Sparse Fieldsets
-                    relativeUrl: sparsefieldsets.html
-        extensibility:
-            name: Extensibility
-            items:
-                layers:
-                    text: The Layers
-                    relativeUrl: layers.html
-                controllers:
-                    text: Controllers
-                    relativeUrl: controllers.html
-                services:
-                    text: Resource Services
-                    relativeUrl: resourceservices.html
-                repositories:
-                    text: Entity Repositories
-                    relativeUrl: entityrepositories.html
-                middleware:
-                    text: Middleware
-                    relativeUrl: middleware.html
-                customqueryformat:
-                    text: Custom Query Formats
-                    relativeUrl: customqueryformat.html
\ No newline at end of file
diff --git a/docs/ContextGraph.md b/docs/ContextGraph.md
deleted file mode 100644
index f5b8394b83..0000000000
--- a/docs/ContextGraph.md
+++ /dev/null
@@ -1,58 +0,0 @@
----
-currentMenu: contextgraph
----
-
-# Context Graph
-
-The [ContextGraph](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Internal/ContextGraph.cs) is a map of all the json:api resources and their relationships that your API serves.
-It is built at app startup and available as a singleton through Dependency Injection. 
-
-When you call `services.AddJsonApi<AppDbContext>()`, the graph is constructed from the context.
-
-### Defining Non-EF Resources
-
-If you have models that are not members of a `DbContext`, 
-you can manually create this graph like so:
-
-```csharp
-// Startup.cs
-public void ConfigureServices(IServiceCollection services)
-{
-    // Add framework services.
-    var mvcBuilder = services.AddMvc();
-
-    services.AddJsonApi(options => {
-        options.Namespace = "api/v1";
-        options.BuildContextGraph((builder) => {
-            builder.AddResource<MyModel>("my-models");
-        });
-    }, mvcBuilder);
-    // ...
-}
-```
-
-### Changing Resource Names
-
-If a DbContext is specified when adding the services, the context will be used to define the resources and their names. By default, these names will be hyphenated.
-
-```csharp
-public class AppDbContext : DbContext {
-    // this will be translated into "my-models"
-    public DbSet<MyModel> MyModels { get; set; }
-}
-```
-
-However, you can specify a custom name like so:
-
-```csharp
-public class AppDbContext : DbContext {
-    // this will be translated into "someModels"
-    [Resource("someModels")]
-    public DbSet<MyModel> MyModels { get; set; }
-}
-```
-
-
-
-
-
diff --git a/docs/Controllers.md b/docs/Controllers.md
deleted file mode 100644
index 0ec47b8774..0000000000
--- a/docs/Controllers.md
+++ /dev/null
@@ -1,93 +0,0 @@
----
-currentMenu: controllers
----
-
-# Controllers
-
-You need to create controllers that inherit from [JsonApiController&lt;TEntity&gt;](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Controllers/JsonApiController.cs).
-
-```csharp
-public class ThingsController : JsonApiController<Thing>
-{
-    public ThingsController(
-        IJsonApiContext jsonApiContext,
-        IResourceService<Thing> resourceService,
-        ILoggerFactory loggerFactory) 
-    : base(jsonApiContext, resourceService, loggerFactory)
-    { }
-}
-```
-
-### Non-Integer Type Keys
-
-If your model is using a type other than `int` for the primary key,
-you should explicitly declare it in the controller
-and service generic type definitions:
-
-```csharp
-public class ThingsController : JsonApiController<Thing, Guid>
-                                //---------------------- ^^^^
-{
-    public ThingsController(
-        IJsonApiContext jsonApiContext,
-        IResourceService<Thing, Guid> resourceService,
-        //--------------------- ^^^^
-        ILoggerFactory loggerFactory) 
-    : base(jsonApiContext, resourceService, loggerFactory)
-    { }
-}
-```
-
-### Limiting Write Access
-
-It is possible to limit write resource access on the controller entirely using the following attributes:
-
-- `NoHttpPost`: disallow POST requests
-- `NoHttpPatch`: disallow PATCH requests
-- `NoHttpDelete`: disallow DELETE requests
-- `HttpReadOnly`: all of the above
-
-```csharp
-[HttpReadOnly]
-public class ThingsController : JsonApiController<Thing>
-{
-    public ThingsController(
-        IJsonApiContext jsonApiContext,
-        IResourceService<Thing> resourceService,
-        ILoggerFactory loggerFactory) 
-    : base(jsonApiContext, resourceService, loggerFactory)
-    { }
-}
-```
-
-### Additional customizations
-
-If you need additional customization at the controller level, you can override the virtual
-methods. Please be aware that this is not the place for advanced business logic
-which should be performed at the [service](resourceservices.html) or [repository](entityrepositories.html) layers. Here is an example override at the controller layer:
-
-```csharp
-public class TodoItemsController : JsonApiController<TodoItem>
-{
-    public TodoItemsController(
-        IJsonApiContext jsonApiContext,
-        IResourceService<TodoItem> resourceService,
-        ILoggerFactory loggerFactory) 
-        : base(jsonApiContext, resourceService, loggerFactory)
-    { }
-
-    [HttpGet]
-    public override async Task<IActionResult> GetAsync()
-    {
-        // custom code
-        if(RequestIsValid() == false)
-            return BadRequest();
-        
-        // return result from base class
-        return await base.GetAsync();
-    }
-
-    // some custom validation logic
-    private bool RequestIsValid() => true;
-}
-```
diff --git a/docs/CustomQueryFormat.md b/docs/CustomQueryFormat.md
deleted file mode 100644
index b23993d333..0000000000
--- a/docs/CustomQueryFormat.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-currentMenu: customqueryformat
----
-
-# Custom Query Formats
-
-For information on the default query parameter formats, see the documentation for each query method.
-
-In order to customize the query formats, you need to implement the `IQueryParser` interface and inject it like so:
-
-```csharp
-services.AddScoped<IQueryParser, FooQueryParser>();
-```
\ No newline at end of file
diff --git a/docs/EntityRepositories.md b/docs/EntityRepositories.md
deleted file mode 100644
index 62d156e427..0000000000
--- a/docs/EntityRepositories.md
+++ /dev/null
@@ -1,44 +0,0 @@
----
-currentMenu: repositories
----
-
-# Entity Repositories
-
-If you want to use EF, but need additional data access logic (such as authorization), you can implement custom methods for accessing the data by creating an implementation of 
-[IEntityRepository&lt;Entity, TId&gt;](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Data/IEntityRepository.cs). If you only need minor changes you can override the 
-methods defined in [DefaultEntityRepository&lt;TEntity, TId&gt;](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs). 
-
-The repository should then be
-add to the service collection in `Startup.cs` like so:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddScoped<IEntityRepository<MyEntity,Guid>, MyAuthorizedEntityRepository>();
-    // ...
-}
-```
-
-A sample implementation that performs data authorization might look like:
-
-```csharp
-public class MyAuthorizedEntityRepository : DefaultEntityRepository<MyEntity>
-{
-    private readonly ILogger _logger;
-    private readonly IAuthenticationService _authenticationService;
-
-    public MyAuthorizedEntityRepository(
-        ILoggerFactory loggerFactory,
-        IJsonApiContext jsonApiContext,
-        IAuthenticationService authenticationService)
-    : base(loggerFactory, jsonApiContext)
-    {
-        _logger = loggerFactory.CreateLogger<MyEntityRepository>();
-        _authenticationService = authenticationService;
-    }
-
-    public override IQueryable<MyEntity> Get()
-    {
-        return base.Get().Where(e => e.UserId == _authenticationService.UserId);
-    }
-}
-```
diff --git a/docs/Errors.md b/docs/Errors.md
deleted file mode 100644
index 59f4f6da21..0000000000
--- a/docs/Errors.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-currentMenu: errors
----
-
-# Custom Errors
-
-By default, errors will only contain the properties defined by the internal [Error](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Internal/Error.cs) class. However, you can create your own by inheriting from `Error` and either throwing it in a `JsonApiException` or returning the error from your controller.
-
-```csharp
-// custom error definition
-public class CustomError : Error {
-    public CustomError(string status, string title, string detail, string myProp)
-    : base(status, title, detail)
-    {
-        MyCustomProperty = myProp;
-    }
-    public string MyCustomProperty { get; set; }
-}
-
-// throwing a custom error
-public void MyMethod() {
-    var error = new CustomError("507", "title", "detail", "custom");
-    throw new JsonApiException(error);
-}
-
-// returning from controller
-[HttpPost]
-public override async Task<IActionResult> PostAsync([FromBody] MyEntity entity)
-{
-    if(_db.IsFull)
-        return Error(new CustomError("507", "Database is full.", "Theres no more room.", "Sorry."));
-
-    if(model.Validations.IsValid == false)
-        return Errors(model.Validations.GetErrors());
-
-    // ...
-}
-```
\ No newline at end of file
diff --git a/docs/Filtering.md b/docs/Filtering.md
deleted file mode 100644
index c258fe4f73..0000000000
--- a/docs/Filtering.md
+++ /dev/null
@@ -1,50 +0,0 @@
----
-currentMenu: filtering
----
-
-# Filtering
-
-You can filter resources by attributes using the `filter` query parameter. 
-By default, all attributes are filterable.
-The filtering strategy we have selected, uses the following form:
-
-```
-?filter[attribute]=value
-```
-
-For operations other than equality, the query can be prefixed with an operation
-identifier):
-
-```
-?filter[attribute]=eq:value
-?filter[attribute]=lt:value
-?filter[attribute]=gt:value
-?filter[attribute]=le:value
-?filter[attribute]=ge:value
-?filter[attribute]=like:value
-```
-
-### Custom Filters
-
-You can customize the filter implementation by overriding the method in the `DefaultEntityRepository` like so:
-
-```csharp
-public class MyEntityRepository : DefaultEntityRepository<MyEntity>
-{
-    public MyEntityRepository(
-    	AppDbContext context,
-        ILoggerFactory loggerFactory,
-        IJsonApiContext jsonApiContext)
-    : base(context, loggerFactory, jsonApiContext)
-    { }
-    
-    public override IQueryable<TEntity> Filter(IQueryable<TEntity> entities,  FilterQuery filterQuery)
-    {
-        // use the base filtering method    
-        entities = base.Filter(entities, filterQuery);
-	
-        // implement custom method
-        return ApplyMyCustomFilter(entities, filterQuery);
-    }
-}
-```
diff --git a/docs/IncludingRelationships.md b/docs/IncludingRelationships.md
deleted file mode 100644
index e11657ebdf..0000000000
--- a/docs/IncludingRelationships.md
+++ /dev/null
@@ -1,54 +0,0 @@
----
-currentMenu: includingrelationships
----
-
-# Including Relationships
-
-JADNC supports [request include params](http://jsonapi-resources.com/v0.9/guide/resources.html#Included-relationships-side-loading-resources) out of the box, for side loading related resources.
-
-Here’s an example from the spec:
-
-```http
-GET /articles/1?include=comments HTTP/1.1
-Accept: application/vnd.api+json
-```
-
-Will get you the following payload:
-
-```json
-{
-  "data": {
-    "type": "articles",
-    "id": "1",
-    "attributes": {
-      "title": "JSON API paints my bikeshed!"
-    },
-    "relationships": {
-      "comments": {
-        "links": {
-          "self": "http://example.com/articles/1/relationships/comments",
-          "related": "http://example.com/articles/1/comments"
-        },
-        "data": [
-          { "type": "comments", "id": "5" },
-          { "type": "comments", "id": "12" }
-        ]
-      }
-    }
-  },
-  "included": [{
-    "type": "comments",
-    "id": "5",
-    "attributes": {
-      "body": "First!"
-    }
-  }, {
-    "type": "comments",
-    "id": "12",
-    "attributes": {
-      "body": "I like XML better"
-    }
-  }]
-}
-```
-
diff --git a/docs/Index.md b/docs/Index.md
deleted file mode 100644
index 64b0861155..0000000000
--- a/docs/Index.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-currentMenu: about
----
-
-# JSON API .Net Core
-
-A framework for building [json:api](http://jsonapi.org/) compliant web servers. It allows you to eliminate a significant amount of boilerplate while offering out-of-the-box features such as sorting, filtering and pagination. This library provides all the required middleware to build a complete server. All you need to focus on is defining the resources and implementing your custom business logic. This library has been designed around dependency injection making extensibility incredibly easy.
\ No newline at end of file
diff --git a/docs/Installation.md b/docs/Installation.md
deleted file mode 100644
index 367d5d3a2e..0000000000
--- a/docs/Installation.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-currentMenu: installation
----
-
-# Installation
-
-- CLI
-```
-$ dotnet add package jsonapidotnetcore
-```
-
-- Visual Studio
-```
-Install-Package JsonApiDotnetCore
-```
-
-- *.csproj
-```xml
-<ItemGroup>
-    <!-- Be sure to check NuGet for the latest version # -->
-    <PackageReference Include="JsonApiDotNetCore" Version="2.0.1" />
-</ItemGroup>
-```
-
-Click [here](https://www.nuget.org/packages/JsonApiDotnetCore/) for the latest NuGet version.
-
-For pre-releases (develop branch), add the [MyGet](https://www.myget.org/feed/Details/research-institute) package feed 
-(https://www.myget.org/F/research-institute/api/v3/index.json) 
-to your nuget configuration.
\ No newline at end of file
diff --git a/docs/Layers.md b/docs/Layers.md
deleted file mode 100644
index 5c71030274..0000000000
--- a/docs/Layers.md
+++ /dev/null
@@ -1,57 +0,0 @@
----
-currentMenu: layers
----
-
-# The Layers
-
-By default, data retrieval is distributed across 3 layers:
-
-1. [JsonApiController](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Controllers/JsonApiController.cs) (required)
-2. [IResourceService](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Services/IResourceService.cs) (default [EntityResourceService](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Services/EntityResourceService.cs))
-3. [IEntityRepository](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Data/IEntityRepository.cs) (default [DefaultEntityRepository](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs))
-
-Customization can be done at any of these layers. However, it is recommended that you make your customizations at the service or the repository layer when possible to keep the controllers free of unnecessary logic. You can use the following as a general rule of
-thumb for where to put business logic:
-
-- **Controller**: simple validation logic that should result in the return of specific HTTP status codes such as model validation
-- **IResourceService**: advanced BL and replacement of data access mechanisms
-- **IEntityRepository**: custom logic that builds on the EF APIs, such as Authorization of data
-
-## Replacing Services / Repositories
-
-Replacing services is done on a per resource basis and can be done through simple DI
-in your Startup.cs file:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services)
-{
-    // custom service
-    services.AddScoped<IEntityRepository<Person>, CustomPersonService>();
-
-    // custom repository
-    services.AddScoped<IEntityRepository<TodoItem>, AuthorizedTodoItemRepository>();
-
-    // ...
-}
-```
-
-## Not Using Entity Framework?
-
-Out of the box, the library uses your `DbContext` to create a "ContextGraph" or map of all your models and their relationships. If, however, you have models that are not members of a `DbContext`, you can manually create this graph like so:
-
-```csharp
-// Startup.cs
-public void ConfigureServices(IServiceCollection services)
-{
-    // Add framework services.
-    var mvcBuilder = services.AddMvc();
-
-    services.AddJsonApi(options => {
-        options.Namespace = "api/v1";
-        options.BuildContextGraph((builder) => {
-            builder.AddResource<MyModel>("my-models");
-        });
-    }, mvcBuilder);
-    // ...
-}
-```
diff --git a/docs/Meta.md b/docs/Meta.md
deleted file mode 100644
index 10b1a23e9a..0000000000
--- a/docs/Meta.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-currentMenu: meta
----
-
-# Meta
-
-Meta objects can be assigned in two ways:
- - Resource meta
- - Request Meta
-
-Resource meta can be defined by implementing `IHasMeta` on the model class:
-
-```csharp
-public class Person : Identifiable<int>, IHasMeta
-{
-    // ...
-
-    public Dictionary<string, object> GetMeta(IJsonApiContext context)
-    {
-        return new Dictionary<string, object> {
-            { "copyright", "Copyright 2015 Example Corp." },
-            { "authors", new string[] { "Jared Nance" } }
-        };
-    }
-}
-```
-
-Request Meta can be added by injecting a service that implements `IRequestMeta`.
-In the event of a key collision, the Request Meta will take precendence. 
diff --git a/docs/Middleware.md b/docs/Middleware.md
deleted file mode 100644
index 681136ca9b..0000000000
--- a/docs/Middleware.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-currentMenu: middleware
----
-
-# Configure Middleware and Services
-
-Add the following to your `Startup.ConfigureServices` method. 
-Replace `AppDbContext` with your DbContext. 
-
-```csharp
-services.AddJsonApi<AppDbContext>();
-```
-
-Add the middleware to the `Startup.Configure` method. 
-Note that under the hood, this will call `app.UseMvc()` 
-so there is no need to add that as well.
-
-```csharp
-app.UseJsonApi();
-```
\ No newline at end of file
diff --git a/docs/Models.md b/docs/Models.md
deleted file mode 100644
index 73d9afdc43..0000000000
--- a/docs/Models.md
+++ /dev/null
@@ -1,106 +0,0 @@
----
-currentMenu: models
----
-
-# Defining Models
-
-Models must implement [IIdentifiable&lt;TId&gt;](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Models/IIdentifiable.cs).
-The easiest way to do this is to inherit [Identifiable&lt;TId&gt;](https://github.com/Research-Institute/json-api-dotnet-core/blob/master/src/JsonApiDotNetCore/Models/Identifiable.cs) where `TId` is the type of the primary key, like so:
-
-```csharp
-public class Person : Identifiable<Guid>
-{ }
-```
-
-You can use the non-generic `Identifiable` if your primary key is an integer:
-
-```csharp
-public class Person : Identifiable
-{ }
-```
-
-If you need to hang annotations or attributes on the `Id` property, you can override the virtual member:
-
-```csharp
-public class Person : Identifiable
-{ 
-    [Key]
-    [Column("person_id")]
-    public override int Id { get; set; }
-}
-```
-
-If your model must inherit from another class, you can always implement the interface yourself.
-In the following example, ApplicationUser inherits IdentityUser which already contains an Id property of
-type string.
-
-```csharp
-public class ApplicationUser 
-: IdentityUser, IIdentifiable<string>
-{
-    [NotMapped]
-    public string StringId { get => this.Id; set => Id = value; }
-}
-```
-
-## Specifying Public Attributes
-
-If you want an attribute on your model to be publicly available, 
-add the `AttrAttribute` and provide the outbound name.
-
-```csharp
-public class Person : Identifiable<int>
-{
-    [Attr("first-name")]
-    public string FirstName { get; set; }
-}
-```
-
-### Immutability
-
-Attributes can be marked as immutable which will prevent `PATCH` requests
-from updating them:
-
-```csharp
-public class Person : Identifiable<int>
-{
-    [Attr("first-name", immutable: true)]
-    public string FirstName { get; set; }
-}
-```
-
-## Relationships
-
-In order for navigation properties to be identified in the model, 
-they should be labeled with the appropriate attribute (either `HasOne` or `HasMany`).
-
-```csharp
-public class Person : Identifiable<int>
-{
-    [Attr("first-name")]
-    public string FirstName { get; set; }
-
-    [HasMany("todo-items")]
-    public virtual List<TodoItem> TodoItems { get; set; }
-}
-```
-
-Dependent relationships should contain a property in the form `{RelationshipName}Id`. 
-For example, a `TodoItem` may have an `Owner` and so the Id attribute should be `OwnerId` like so:
-
-```csharp
-public class TodoItem : Identifiable<int>
-{
-    [Attr("description")]
-    public string Description { get; set; }
-
-    public int OwnerId { get; set; }
-
-    [HasOne("owner")]
-    public virtual Person Owner { get; set; }
-}
-```
-
-## Resource Names
-
-See [ContextGraph](contextGraph.html) for details on how the resource names are determined.
\ No newline at end of file
diff --git a/docs/Operations.md b/docs/Operations.md
deleted file mode 100644
index 697f9171b2..0000000000
--- a/docs/Operations.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-currentMenu: operations
----
-
-# Operations
-
-Operations is currently an unofficial proposal. It allows you to perform bulk operations in a single transaction. 
-
-### Enabling
-
-To enable the operations extension, modify you `Startup.ConfigureServices` method:
-
-```csharp
-services.AddJsonApi<AppDbContext>(opt => opt.EnableExtension(JsonApiExtension.Operations));
-```
-
-### Controllers
-
-To create a bulk operations controller, inherit `JsonApiOperationsController`:
-
-```csharp
-[Route("api/bulk")]
-public class OperationsController : JsonApiOperationsController
-{
-    public OperationsController(IOperationsProcessor processor)
-        : base(processor)
-    { }
-}
-```
-
-### Example
-
-There is a working example in the `/src/examples/OperationsExample` directory of the repository.
\ No newline at end of file
diff --git a/docs/Options.md b/docs/Options.md
deleted file mode 100644
index 3f94f4031e..0000000000
--- a/docs/Options.md
+++ /dev/null
@@ -1,111 +0,0 @@
----
-currentMenu: options
----
-
-# Global Options
-
-## Client Generated Ids
-
-By default, the server will respond with a `403 Forbidden` HTTP Status Code if a `POST` request is
-received with a client generated id. However, this can be allowed by setting the `AllowClientGeneratedIds`
-flag in the options:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi<AppDbContext>(
-        opt => opt.AllowClientGeneratedIds = true);
-    // ...
-}
-```
-
-## Pagination
-
-If you would like pagination implemented by default, you can specify the page size
-when setting up the services:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi<AppDbContext>(
-        opt => opt.DefaultPageSize = 10);
-    // ...
-}
-```
-
-### Total Record Count
-
-The total number of records can be added to the document meta by setting it in the options:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi<AppDbContext>(opt =>
-    {
-        opt.DefaultPageSize = 5;
-        opt.IncludeTotalRecordCount = true;
-    });
-    // ...
-}
-```
-
-## Relative Links
-
-All links are absolute by default. However, you can configure relative links:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi<AppDbContext>(
-        opt => opt.RelativeLinks = true);
-    // ...
-}
-```
-
-
-```http
-GET /api/v1/articles/4309 HTTP/1.1
-Accept: application/vnd.api+json
-```
-
-```json
-{
-    "type": "articles",
-    "id": "4309",
-    "attributes": {
-        "name": "Voluptas iure est molestias."
-    },
-    "relationships": {
-        "author": {
-            "links": {
-                "self": "/api/v1/articles/4309/relationships/author",
-                "related": "/api/v1/articles/4309/author"
-            }
-        }
-    }
-}
-```
-
-## Custom Query Parameters
-
-If you would like to use custom query params (parameters not reserved by the json:api specification), you can set `AllowCustomQueryParameters = true`. The default behavior is to return an `HTTP 400 Bad Request` for unknown query parameters.
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi<AppDbContext>(
-        opt => opt.AllowCustomQueryParameters = true);
-    // ...
-}
-```
-
-## Custom Serializer Settings
-
-We use Json.Net for all serialization needs. If you want to change the default serializer settings, you can:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi<AppDbContext>(
-        opt => opt.SerializerSettings = new JsonSerializerSettings()
-        {
-            NullValueHandling = NullValueHandling.Ignore,
-            ContractResolver = new DasherizedResolver()
-        });
-    // ...
-}
-```
\ No newline at end of file
diff --git a/docs/Pagination.md b/docs/Pagination.md
deleted file mode 100644
index 7d70773757..0000000000
--- a/docs/Pagination.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-currentMenu: pagination
----
-
-# Pagination
-
-Resources can be paginated. 
-The following query would set the page size to 10 and get page 2.
-
-```
-?page[size]=10&page[number]=2
-```
-
-If you would like pagination implemented by default, you can specify the page size
-when setting up the services:
-
-```C#
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi<AppDbContext>(
-        opt => opt.DefaultPageSize = 10);
-    // ...
-}
-```
diff --git a/docs/ResourceServices.md b/docs/ResourceServices.md
deleted file mode 100644
index 17e7763835..0000000000
--- a/docs/ResourceServices.md
+++ /dev/null
@@ -1,126 +0,0 @@
----
-currentMenu: services
----
-
-# Resource Services
-
-The [IResourceService](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Services/Contract/IResourceService.cs) acts as a service layer between the controller and the data access
-layer. This allows you to customize it however you want and not be dependent upon Entity
-Framework. This is also a good place to implement custom business logic.
-
-### Supplementing Default Behavior
-
-A simple example would be to send notifications when an entity gets created:
-
-```csharp
-public class TodoItemService : EntityResourceService<TodoItem> {
-    
-    private readonly INotificationService _notificationService;
-
-    public TodoItemService(
-        IJsonApiContext jsonApiContext,
-        IEntityRepository<T, TId> repository,
-        ILoggerFactory loggerFactory,
-        // Get the notification service via DI
-        INotificationService notificationService) 
-    : base(jsonApiContext, repository, loggerFactory)
-    {
-        _notificationService = notificationService;
-    }
-
-    public override async Task<TEntity> CreateAsync(TEntity entity)
-    {
-        // call the base implementation which uses Entity Framework
-        var newEntity = await base.CreateAsync(entity);
-        
-        // custom code
-        _notificationService.Notify($"Entity created: { newEntity.Id }");
-
-        // don't forget to return the new entity
-        return entity;
-    }
-}
-```
-
-### Not Using Entity Framework?
-
-As previously discussed, this library uses Entity Framework by default. 
-If you'd like to use another ORM that does not implement `IQueryable`, 
-you can inject a custom service like so:
-
-```csharp
-// Startup.cs
-public void ConfigureServices(IServiceCollection services)
-{
-    // add the service override for MyModel
-    services.AddScoped<IResourceService<MyModel>, MyModelService>();
-    
-    // add your own DAO
-    services.AddScoped<IMyModelDAL, MyModelDAL>();
-    // ...
-}
-
-
-// MyModelService.cs
-public class MyModelService : IResourceService<MyModel>
-{
-    private readonly IMyModelDAL _dal;
-    public MyModelService(IMyModelDAL dal)
-    { 
-        _dal = dal;
-    } 
-
-    public Task<IEnumerable<MyModel>> GetAsync()
-    {
-        return await _dal.GetModelAsync();
-    }
-}
-```
-
-### Limited Requirements
-
-In some cases it may be necessary to only expose a few methods on the resource.
-For this reason, we have created a hierarchy of service interfaces that can be used to get the
-exact implementation you require. Below is a table outlining these interfaces:
-
-![interfaces](service_table.png)
-
-
- In order to take advantage of these interfaces you first need to inject the service for each implemented interface. 
- Using Autofac, as an example, this is simply:
-
-```csharp
-public class MyResourceService : ICreateService<MyResource>, IDeleteService<MyResource> {
-   // ...
-}
-```
-
-```csharp
-public class Startup {
-  public IServiceProvider ConfigureServices(IServiceCollection services) {
-    builder.RegisterType<MyResourceService>().AsImplementedInterfaces();
-  }
-}
-```
-
-Then in the controller, you should inherit the base controller and pass the services into
-the named, optional base parameters:
-
-```csharp
-public class MyResourcesController : BaseJsonApiController<MyResource> {
-
-    public MyResourcesController(
-        IJsonApiContext jsonApiContext, 
-        ICreateService<MyResource> create,
-        IDeleteService<MyResource> delete
-    ) : base(jsonApiContext, create: create, delete: delete) { }
-
-    [HttpPost]
-    public override async Task<IActionResult> PostAsync([FromBody] MyResource entity) 
-        => await base.PostAsync(entity);
-
-    [HttpDelete("{id}")]
-    public override async Task<IActionResult>DeleteAsync(int id) 
-        => await base.DeleteAsync(id);
-}
-```
diff --git a/docs/Routing.md b/docs/Routing.md
deleted file mode 100644
index 008438dd39..0000000000
--- a/docs/Routing.md
+++ /dev/null
@@ -1,65 +0,0 @@
----
-currentMenu: routing
----
-
-# Routing
-
-By default the library will configure routes for each controller. 
-Based on the [recommendations](http://jsonapi.org/recommendations/)
-outlined in the JSONAPI spec, routes are hyphenated.
-
-```http
-GET /api/compound-models HTTP/1.1
-Accept: application/vnd.api+json
-```
-
-## Namespacing and Versioning URLs
-
-You can add a namespace to the URL by specifying it in `ConfigureServices`:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi<AppDbContext>(
-        opt => opt.Namespace = "api/v1");
-}
-```
-
-## Disable Convention
-
-You can disable the dasherized convention and specify your own template
-by using the `DisableRoutingConvention` Attribute. 
-
-```csharp
-[Route("[controller]")]
-[DisableRoutingConvention]
-public class CamelCasedModelsController : JsonApiController<CamelCasedModel> {
-    public CamelCasedModelsController(
-        IJsonApiContext jsonApiContext,
-        IResourceService<CamelCasedModel> resourceService,
-        ILoggerFactory loggerFactory) 
-        : base(jsonApiContext, resourceService, loggerFactory)
-    { }
-}
-```
-
-It is important to note that your routes *must* still end with the model name in the same format
-as the resource name. This is so that we can build accurrate resource links in the json:api document.
-For example, if you define a resource as `MyModels` the controller route must match:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) {
-    services.AddJsonApi(options => {
-        options.BuildContextGraph((builder) => {
-            // resource definition
-            builder.AddResource<TodoItem>("myModels");
-        });
-    });
-}
-
-// controller definition
-[Route("api/myModels")]
-[DisableRoutingConvention]
-public class TodoItemsController : JsonApiController<TodoItem> { 
-    //...
-}
-```
diff --git a/docs/Sorting.md b/docs/Sorting.md
deleted file mode 100644
index 6a5367d8d9..0000000000
--- a/docs/Sorting.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-currentMenu: sorting
----
-
-# Sorting
-
-Resources can be sorted by an attribute:
-
-```
-?sort=attribute // ascending
-?sort=-attribute // descending
-```
diff --git a/docs/SparseFieldsets.md b/docs/SparseFieldsets.md
deleted file mode 100644
index 16e66a2c89..0000000000
--- a/docs/SparseFieldsets.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-currentMenu: sparsefields
----
-
-# Sparse Fieldsets
-
-We currently support top-level field selection. 
-What this means is you can restrict which fields are returned by a query using the `fields` query parameter, but this does not yet apply to included relationships.
-
-- Currently valid:
-```http
-GET /articles?fields[articles]=title,body HTTP/1.1
-Accept: application/vnd.api+json
-```
-
-- Not yet supported:
-```http
-GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1
-Accept: application/vnd.api+json
-```
\ No newline at end of file
diff --git a/docs/Usage.md b/docs/Usage.md
deleted file mode 100644
index 07ac168a21..0000000000
--- a/docs/Usage.md
+++ /dev/null
@@ -1,144 +0,0 @@
----
-currentMenu: usage
----
-
-# Usage
-
-The most basic use case leverages Entity Framework. 
-The shortest path to a running API looks like:
-
-- Create a new web app
-- Install
-- Define models
-- Define the DbContext
-- Define controllers
-- Add Middleware and Services
-- Seed the database
-- Run Migrations
-- Start the app
-
-This page will walk you through the **simplest** use case. More detailed examples can be found in the detailed usage subsections.
-
-
-### Create a New Web App
-
-```
-$ mkdir MyApp
-$ cd MyApp
-$ dotnet new webapi
-```
-
-### Install
-
-See [Installation](installation.html)
-
-### Models
-
-Define your domain models such that they implement `IIdentifiable<TId>`.
-The easiest way to do this is to inherit `Identifiable`:
-
-```csharp
-public class Person : Identifiable
-{ 
-    [Attr("name")]
-    public string Name { get; set; }
-}
-```
-
-### DbContext
-
-Nothing special here, just an ordinary DbContext
-
-```csharp
-public class AppDbContext : DbContext
-{
-    public AppDbContext(DbContextOptions<AppDbContext> options)
-        : base(options) { }
-        
-    public DbSet<Person> People { get; set; }
-}
-```
-
-### Controllers
-
-You need to create controllers that inherit from `JsonApiController<TEntity>` or `JsonApiController<TEntity, TId>`
-where `TEntity` is the model that inherits from `Identifiable<TId>`.
-
-```csharp
-public class PeopleController : JsonApiController<Person>
-{
-    public PeopleController(
-        IJsonApiContext jsonApiContext,
-        IResourceService<Person> resourceService,
-        ILoggerFactory loggerFactory) 
-    : base(jsonApiContext, resourceService, loggerFactory)
-    { }
-}
-```
-
-### Middleware and Services
-
-Finally, add the services by adding the following to your 
-`Startup.ConfigureServices`:
-
-```csharp
-public IServiceProvider ConfigureServices(IServiceCollection services) 
-{
-    // add the db context like you normally would
-    services.AddDbContext<AppDbContext>(options =>
-    { // use whatever provider you want, this is just an example
-        options.UseNpgsql(GetDbConnectionString());
-    }, ServiceLifetime.Transient);
-
-    // add jsonapi dotnet core
-    services.AddJsonApi<AppDbContext>();
-    // ...
-}
-```
-
-Add the middleware to the `Startup.Configure` method. 
-Note that under the hood, this will call `app.UseMvc()` 
-so there is no need to add that as well.
-
-```csharp
-public void Configure(IApplicationBuilder app)
-{
-    app.UseJsonApi();
-}
-```
-
-### Seeding the Database
-
-One way to seed the database is in your Configure method:
-
-```csharp
-public void Configure(
-            IApplicationBuilder app,
-            AppDbContext context)
-{
-    context.Database.EnsureCreated();
-    if(context.People.Count == 0) 
-    {
-        context.People.Add(new Person {
-            Name = "John Doe"
-        });
-        context.SaveChanges();
-    }
-    // ...
-    app.UseJsonApi();
-}
-```
-
-### Run Migrations
-
-```
-$ dotnet ef migrations add AddPeople
-$ dotnet ef database update
-```
-
-### Start the App
-
-```
-$ dotnet run
-$ curl http://localhost:5000/people
-```
diff --git a/docs/service_table.png b/docs/service_table.png
deleted file mode 100644
index d6ae6113701fd95297b6f233c2e1a06b1ae6ff00..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 169430
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
URm3p;(Jt_3c)|ozuImu-Ujne*k^lez


From d62df1c6217d5eabdca1b370ab6aadc84337861d Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 22 Apr 2018 07:43:59 -0500
Subject: [PATCH 133/227] chore(contrib): link to documentation

---
 CONTRIBUTING.MD | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD
index 0e14787fec..8ce50e6c68 100644
--- a/CONTRIBUTING.MD
+++ b/CONTRIBUTING.MD
@@ -2,10 +2,14 @@
 
 ## Workflow
 
-1. Search through the issues to see if your particular issue has already been discovered and possibly addressed
-2. Open an issue if you can't find anything helpful
-3. Open a PR for proposed changes
+1.  Search through the issues to see if your particular issue has already been discovered and possibly addressed
+2.  Open an issue if you can't find anything helpful
+3.  Open a PR for proposed changes
 
 ## Commit Guidelines
 
 I have chosen to loosely follow the [Angular Commit Guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit)
+
+# Documentation
+
+If you'd like to help us improve our documentation, please checkout our [GitHub pages repository](https://github.com/json-api-dotnet/json-api-dotnet.github.io) where we host our documentation.

From 0d1ba6e9fa3b76dad9d9b280e6d7b1c9d64a7417 Mon Sep 17 00:00:00 2001
From: Corey Floyd <cfloyd@appriver.com>
Date: Mon, 23 Apr 2018 07:54:23 -0500
Subject: [PATCH 134/227] #162 Adds parameter name to new attribute value for
 example.

---
 src/Examples/JsonApiDotNetCoreExample/Models/Person.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs
index 5aa7c83c12..d140b23b6b 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/Person.cs
@@ -21,7 +21,7 @@ public class Person : Identifiable, IHasMeta
         [HasMany("todo-collections")]
         public virtual List<TodoItemCollection> TodoItemCollections { get; set; }
         
-        [HasOne("unincludeable-item", Link.All, false)]
+        [HasOne("unincludeable-item", Link.All, canInclude: false)]
         public virtual TodoItem UnIncludeableItem { get; set; }
 
         public Dictionary<string, object> GetMeta(IJsonApiContext context)

From 2b916465b3570c4c3e25edbe31e6b805b34e9854 Mon Sep 17 00:00:00 2001
From: Corey Floyd <cfloyd@appriver.com>
Date: Tue, 24 Apr 2018 13:09:27 -0500
Subject: [PATCH 135/227] #258 Adds new utility to provide substrings of a
 given string as Span<char> given a char delimeter. Language version updated
 to 7.2 due to need for ref Struct to utilize Span<T> as a field.

---
 .../Internal/SpanSplitter.cs                  |  64 +++++++++++
 .../JsonApiDotNetCore.csproj                  |   7 ++
 test/UnitTests/Internal/SpanSplitterTests.cs  | 107 ++++++++++++++++++
 3 files changed, 178 insertions(+)
 create mode 100644 src/JsonApiDotNetCore/Internal/SpanSplitter.cs
 create mode 100644 test/UnitTests/Internal/SpanSplitterTests.cs

diff --git a/src/JsonApiDotNetCore/Internal/SpanSplitter.cs b/src/JsonApiDotNetCore/Internal/SpanSplitter.cs
new file mode 100644
index 0000000000..268bcab195
--- /dev/null
+++ b/src/JsonApiDotNetCore/Internal/SpanSplitter.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using JsonApiDotNetCore.Extensions;
+
+namespace JsonApiDotNetCore.Internal
+{
+    public readonly ref struct SpanSplitter
+    {
+        private readonly ReadOnlySpan<char> _span;
+        private readonly List<int> _delimeterIndexes;
+        private readonly List<Tuple<int, int>> _substringIndexes;
+
+        public int Count => _substringIndexes.Count();
+        public ReadOnlySpan<char> this[int index] => GetSpanForSubstring(index + 1);
+
+        public SpanSplitter(ref string str, char delimeter)
+        {
+            _span = str.AsSpan();
+            _delimeterIndexes = str.IndexesOf(delimeter).ToList();
+            _substringIndexes = new List<Tuple<int, int>>();
+            BuildSubstringIndexes();
+        }
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override bool Equals(object obj) => throw new NotSupportedException();
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override int GetHashCode() => throw new NotSupportedException();
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override string ToString() => throw new NotSupportedException();
+
+        private ReadOnlySpan<char> GetSpanForSubstring(int substringNumber)
+        {
+            if (substringNumber > Count)
+            {
+                throw new ArgumentOutOfRangeException($"There are only {Count} substrings given the delimeter and base string provided");
+            }
+
+            var indexes = _substringIndexes[substringNumber - 1];
+            return _span.Slice(indexes.Item1, indexes.Item2);
+        }
+        
+        private void BuildSubstringIndexes()
+        {
+            var start = 0;
+            var end = 0;
+            foreach (var index in _delimeterIndexes)
+            {
+                end = index;
+                if (start > end) break;
+                _substringIndexes.Add(new Tuple<int, int>(start, end - start));
+                start = ++end;
+            }
+
+            if (end <= _span.Length)
+            {
+                _substringIndexes.Add(new Tuple<int, int>(start, _span.Length - start));
+            }
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index c4b9a6d932..f13c10ead7 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -21,6 +21,7 @@
     <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
     <PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftLoggingVersion)" />
+    <PackageReference Include="System.Memory" Version="4.5.0-preview2-26406-04" />
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
   </ItemGroup>
 
@@ -31,6 +32,12 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
     <DocumentationFile>bin\Release\netstandard2.0\JsonApiDotNetCore.xml</DocumentationFile>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
+    <LangVersion>7.2</LangVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
+    <LangVersion>7.2</LangVersion>
+  </PropertyGroup>
   <ItemGroup Condition="$(IsWindows)=='true'">
     <PackageReference Include="docfx.console" Version="2.33.0" />
   </ItemGroup>
diff --git a/test/UnitTests/Internal/SpanSplitterTests.cs b/test/UnitTests/Internal/SpanSplitterTests.cs
new file mode 100644
index 0000000000..016ee8ec82
--- /dev/null
+++ b/test/UnitTests/Internal/SpanSplitterTests.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using JsonApiDotNetCore.Internal;
+using Xunit;
+
+namespace UnitTests.Internal
+{
+    public class SpanSplitterTests : SpanSplitterTestsBase
+    {
+        [Fact]
+        public void StringWithDelimeterSplitsIntoCorrectNumberSubstrings()
+        {
+            GivenMultipleCommaDelimetedString();
+            WhenSplittingIntoSubstrings();
+            AssertCorrectSubstringsReturned();
+        }
+
+        [Fact]
+        public void StringWithSingleDelimeterSplitsIntoCorrectNumberSubstrings()
+        {
+            GivenSingleCommaDelimetedString();
+            WhenSplittingIntoSubstrings();
+            AssertCorrectSubstringsReturned();
+        }
+
+        [Fact]
+        public void StringWithNoDelimeterSplitsIntoSingleSubstring()
+        {
+            GivenNonCommaDelimetedString();
+            WhenSplittingIntoSubstrings();
+            AssertCorrectSubstringsReturned();
+        }
+
+        [Fact]
+        public void StringWithDelimeterAtEndSplitsIntoCorrectSubstring()
+        {
+            GivenStringWithCommaDelimeterAtEnd();
+            WhenSplittingIntoSubstrings();
+            AssertCorrectSubstringsReturned();
+        }
+
+        [Fact]
+        public void StringWithDelimeterAtBeginningSplitsIntoCorrectSubstring()
+        {
+            GivenStringWithCommaDelimeterAtBeginning();
+            WhenSplittingIntoSubstrings();
+            AssertCorrectSubstringsReturned();
+        }
+    }
+
+    public abstract class SpanSplitterTestsBase
+    {
+        private string _baseString;
+        private char _delimeter;
+        private readonly List<string> _substrings = new List<string>();
+
+        protected void GivenMultipleCommaDelimetedString()
+        {
+            _baseString = "This,Is,A,TestString";
+            _delimeter = ',';
+        }
+
+        protected void GivenSingleCommaDelimetedString()
+        {
+            _baseString = "This,IsATestString";
+            _delimeter = ',';
+        }
+
+        protected void GivenNonCommaDelimetedString()
+        {
+            _baseString = "ThisIsATestString";
+        }
+
+        protected void GivenStringWithCommaDelimeterAtEnd()
+        {
+            _baseString = "This,IsATestString,";
+            _delimeter = ',';
+        }
+
+        protected void GivenStringWithCommaDelimeterAtBeginning()
+        {
+            _baseString = "/api/v1/articles";
+            _delimeter = '/';
+        }
+
+        protected void WhenSplittingIntoSubstrings()
+        {
+            SpanSplitter spanSplitter;
+            spanSplitter = new SpanSplitter(ref _baseString, _delimeter);
+            for (var i = 0; i < spanSplitter.Count; i++)
+            {
+                var span = spanSplitter[i];
+                _substrings.Add(span.ToString());
+            }
+        }
+
+        protected void AssertCorrectSubstringsReturned()
+        {
+            Assert.NotEmpty(_substrings);
+            var stringSplitArray = _baseString.Split(_delimeter);
+            Assert.Equal(stringSplitArray.Length, _substrings.Count);
+            Assert.True(stringSplitArray.SequenceEqual(_substrings));
+        }
+    }
+}

From 85f09d171ded19c828659b1dda62e16960bbd478 Mon Sep 17 00:00:00 2001
From: Corey Floyd <cfloyd@appriver.com>
Date: Tue, 24 Apr 2018 13:20:19 -0500
Subject: [PATCH 136/227] #258 Updates LinkBuilder, RelatedAttrFilterQuery,
 RequestMiddleware, JsonApiContext, and QueryParser  to utilize new
 SpanSplitter library to avoid unnecessary intermediate string creation.

---
 src/JsonApiDotNetCore/Builders/LinkBuilder.cs | 23 ++++++++++---------
 .../Extensions/StringExtensions.cs            | 13 +++++++++++
 .../Internal/Query/RelatedAttrFilterQuery.cs  | 15 ++++++------
 .../Middleware/RequestMiddleware.cs           |  8 +++++--
 .../Services/JsonApiContext.cs                |  9 +++++---
 src/JsonApiDotNetCore/Services/QueryParser.cs | 21 +++++++++++------
 6 files changed, 59 insertions(+), 30 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
index dced1225a9..8b4b30f948 100644
--- a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
@@ -1,3 +1,6 @@
+using System;
+using System.Text;
+using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
 
@@ -20,20 +23,18 @@ public string GetBasePath(HttpContext context, string entityName)
                 : $"{r.Scheme}://{r.Host}{GetNamespaceFromPath(r.Path, entityName)}";
         }
 
-        private string GetNamespaceFromPath(string path, string entityName)
+        private static string GetNamespaceFromPath(string path, string entityName)
         {
-            var nSpace = string.Empty;
-            var segments = path.Split('/');
-
-            for (var i = 1; i < segments.Length; i++)
+            var sb = new StringBuilder();
+            var entityNameSpan = entityName.AsSpan();
+            var subSpans = new SpanSplitter(ref path, '/');
+            for (var i = 1; i < subSpans.Count; i++)
             {
-                if (segments[i].ToLower() == entityName)
-                    break;
-
-                nSpace += $"/{segments[i]}";
+                var span = subSpans[i];
+                if (entityNameSpan.SequenceEqual(span)) break;
+                sb.Append($"/{span.ToString()}");
             }
-
-            return nSpace;
+            return sb.ToString();
         }
 
         public string GetSelfRelationLink(string parent, string parentId, string child)
diff --git a/src/JsonApiDotNetCore/Extensions/StringExtensions.cs b/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
index 24d5bc8d58..e962baae3d 100644
--- a/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
@@ -1,3 +1,5 @@
+using System;
+using System.Collections.Generic;
 using System.Text;
 
 namespace JsonApiDotNetCore.Extensions
@@ -50,5 +52,16 @@ public static string Dasherize(this string str)
             }
             return str;
         }
+
+        public static IEnumerable<int> IndexesOf(this string str, char delimeter)
+        {
+            var indexes = new List<int>();
+            for (var i = str.IndexOf(delimeter); i > -1 ; i = str.IndexOf(delimeter, i+1))
+            {
+                indexes.Add(i);
+            }
+            return indexes;
+        }
+        
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
index 5ec658873d..f4d8114a70 100644
--- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
@@ -8,20 +8,21 @@ namespace JsonApiDotNetCore.Internal.Query
     public class RelatedAttrFilterQuery : BaseFilterQuery
     {
         private readonly IJsonApiContext _jsonApiContext;
-
+        
         public RelatedAttrFilterQuery(
             IJsonApiContext jsonApiCopntext,
             FilterQuery filterQuery)
         {
             _jsonApiContext = jsonApiCopntext;
-
-            var relationshipArray = filterQuery.Attribute.Split('.');
-
-            var relationship = GetRelationship(relationshipArray[0]);
+            var filterQueryAttribute = filterQuery.Attribute;
+            var relationshipSubSpans = new SpanSplitter(ref filterQueryAttribute, '.');
+            var relationship1 = relationshipSubSpans[0].ToString();
+            var relationship2 = relationshipSubSpans[1].ToString();
+            var relationship = GetRelationship(relationshipSubSpans[0].ToString());
             if (relationship == null)
-                throw new JsonApiException(400, $"{relationshipArray[1]} is not a valid relationship on {relationshipArray[0]}.");
+                throw new JsonApiException(400, $"{relationship2} is not a valid relationship on {relationship1}.");
 
-            var attribute = GetAttribute(relationship, relationshipArray[1]);
+            var attribute = GetAttribute(relationship, relationship2);
 
             if (attribute == null)
                 throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
diff --git a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
index 6e2612c9a6..54a116489d 100644
--- a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
+++ b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Internal;
 using Microsoft.AspNetCore.Http;
@@ -54,8 +55,11 @@ private static bool IsValidAcceptHeader(HttpContext context)
 
         private static bool ContainsMediaTypeParameters(string mediaType)
         {
-            var mediaTypeArr = mediaType.Split(';');
-            return (mediaTypeArr[0] ==  Constants.ContentType && mediaTypeArr.Length == 2);
+            const char delimeter = ';';
+            var sliceLength = mediaType.IndexOf(delimeter);
+            if (sliceLength < 0) return false;
+            var mediaTypeSlice = mediaType.AsSpan().Slice(0, sliceLength);
+            return mediaTypeSlice.Length == 2 && mediaTypeSlice.SequenceEqual(Constants.ContentType.AsSpan());
         }
 
         private static void FlushResponse(HttpContext context, int statusCode)
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 1ebf5aeea1..0f07624a4e 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -64,7 +64,7 @@ public IJsonApiContext ApplyContext<T>(object controller)
                 throw new JsonApiException(500, $"A resource has not been properly defined for type '{typeof(T)}'. Ensure it has been registered on the ContextGraph.");
 
             var context = _httpContextAccessor.HttpContext;
-            var path = context.Request.Path.Value.Split('/');
+            var requestPath = context.Request.Path.Value;
 
             if (context.Request.Query.Count > 0)
             {
@@ -75,10 +75,13 @@ public IJsonApiContext ApplyContext<T>(object controller)
             var linkBuilder = new LinkBuilder(this);
             BasePath = linkBuilder.GetBasePath(context, _controllerContext.RequestEntity.EntityName);
             PageManager = GetPageManager();
-            IsRelationshipPath = path[path.Length - 2] == "relationships";
+
+            var pathSpans = new SpanSplitter(ref requestPath, '/');
+            IsRelationshipPath = pathSpans[pathSpans.Count - 2].ToString() == "relationships";
+
             return this;
         }
-
+        
         private PageManager GetPageManager()
         {
             if (Options.DefaultPageSize == 0 && (QuerySet == null || QuerySet.PageQuery.PageSize == 0))
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 5e705f4bc9..f988664c62 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -3,6 +3,7 @@
 using System.Linq;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Controllers;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
@@ -93,16 +94,16 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
             // expected input = filter[id]=1
             // expected input = filter[id]=eq:1
             var queries = new List<FilterQuery>();
+            var openBracketIndex = key.IndexOf(OPEN_BRACKET);
+            var closedBracketIndex = key.IndexOf(CLOSE_BRACKET);
+            var propertyNameSlice = key.AsSpan().Slice(openBracketIndex + 1, closedBracketIndex - openBracketIndex - 1);
+            var propertyName = propertyNameSlice.ToString();
 
-            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
-
-            var values = value.Split(COMMA);
-            foreach (var val in values)
+            var spanSplitter = new SpanSplitter(ref value, COMMA);
+            for (var i = 0; i < spanSplitter.Count; i++)
             {
-                (var operation, var filterValue) = ParseFilterOperation(val);
-                queries.Add(new FilterQuery(propertyName, filterValue, operation));
+                queries.Add(BuildFilterQuery(spanSplitter[i], propertyName));
             }
-
             return queries;
         }
 
@@ -235,5 +236,11 @@ protected virtual AttrAttribute GetAttribute(string propertyName)
                 throw new JsonApiException(400, $"Attribute '{propertyName}' does not exist on resource '{_controllerContext.RequestEntity.EntityName}'", e);
             }
         }
+
+        private FilterQuery BuildFilterQuery(ReadOnlySpan<char> query, string propertyName)
+        {
+            var (operation, filterValue) = ParseFilterOperation(query.ToString());
+            return new FilterQuery(propertyName, filterValue, operation);
+        }
     }
 }

From a7d33903f89e4e95b9a0f28c716da5698d8a8ab3 Mon Sep 17 00:00:00 2001
From: Corey Floyd <cfloyd@appriver.com>
Date: Tue, 24 Apr 2018 13:41:51 -0500
Subject: [PATCH 137/227] #258 Fixes Error in ContainsMediaTypeParameters
 method's logic. ContentNegotion tests pass.

---
 src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
index 54a116489d..a7bbebb7f4 100644
--- a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
+++ b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
@@ -56,10 +56,9 @@ private static bool IsValidAcceptHeader(HttpContext context)
         private static bool ContainsMediaTypeParameters(string mediaType)
         {
             const char delimeter = ';';
-            var sliceLength = mediaType.IndexOf(delimeter);
-            if (sliceLength < 0) return false;
-            var mediaTypeSlice = mediaType.AsSpan().Slice(0, sliceLength);
-            return mediaTypeSlice.Length == 2 && mediaTypeSlice.SequenceEqual(Constants.ContentType.AsSpan());
+            var subSpans = new SpanSplitter(ref mediaType, delimeter);
+            if (subSpans.Count == 0) return false;
+            return subSpans.Count == 2 && subSpans[0].ToString() == Constants.ContentType;
         }
 
         private static void FlushResponse(HttpContext context, int statusCode)

From 6ab917f732ed8b5de634c5e7c3c70d597720eb34 Mon Sep 17 00:00:00 2001
From: Corey Floyd <fourfloyds@gmail.com>
Date: Tue, 24 Apr 2018 20:31:10 -0500
Subject: [PATCH 138/227] #258 Removes extra ToString() on the span and fixes
 naming to be more accurate

---
 .../Internal/Query/RelatedAttrFilterQuery.cs         | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
index f4d8114a70..8602a24f30 100644
--- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
@@ -15,14 +15,14 @@ public RelatedAttrFilterQuery(
         {
             _jsonApiContext = jsonApiCopntext;
             var filterQueryAttribute = filterQuery.Attribute;
-            var relationshipSubSpans = new SpanSplitter(ref filterQueryAttribute, '.');
-            var relationship1 = relationshipSubSpans[0].ToString();
-            var relationship2 = relationshipSubSpans[1].ToString();
-            var relationship = GetRelationship(relationshipSubSpans[0].ToString());
+            var filterQuerySubSpans = new SpanSplitter(ref filterQueryAttribute, '.');
+            var subSpan1 = filterQuerySubSpans[0].ToString();
+            var subSpan2 = filterQuerySubSpans[1].ToString();
+            var relationship = GetRelationship(subSpan1);
             if (relationship == null)
-                throw new JsonApiException(400, $"{relationship2} is not a valid relationship on {relationship1}.");
+                throw new JsonApiException(400, $"{subSpan2} is not a valid relationship on {subSpan1}.");
 
-            var attribute = GetAttribute(relationship, relationship2);
+            var attribute = GetAttribute(relationship, subSpan2);
 
             if (attribute == null)
                 throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");

From 86d76356f72a04d79d64a3043181578744bd06fc Mon Sep 17 00:00:00 2001
From: Corey Floyd <fourfloyds@gmail.com>
Date: Tue, 24 Apr 2018 20:52:15 -0500
Subject: [PATCH 139/227] #258 Adds extension method for splitting with spans.
 Updates usages and unit tests to use extension method.

---
 src/JsonApiDotNetCore/Builders/LinkBuilder.cs              | 3 ++-
 src/JsonApiDotNetCore/Extensions/StringExtensions.cs       | 6 ++++++
 .../Internal/Query/RelatedAttrFilterQuery.cs               | 3 ++-
 src/JsonApiDotNetCore/Internal/SpanSplitter.cs             | 7 ++++++-
 src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs      | 3 ++-
 src/JsonApiDotNetCore/Services/JsonApiContext.cs           | 3 ++-
 src/JsonApiDotNetCore/Services/QueryParser.cs              | 2 +-
 test/UnitTests/Internal/SpanSplitterTests.cs               | 3 ++-
 8 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
index 8b4b30f948..b2bfcae168 100644
--- a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Text;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
@@ -27,7 +28,7 @@ private static string GetNamespaceFromPath(string path, string entityName)
         {
             var sb = new StringBuilder();
             var entityNameSpan = entityName.AsSpan();
-            var subSpans = new SpanSplitter(ref path, '/');
+            var subSpans = path.SpanSplit('/');
             for (var i = 1; i < subSpans.Count; i++)
             {
                 var span = subSpans[i];
diff --git a/src/JsonApiDotNetCore/Extensions/StringExtensions.cs b/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
index e962baae3d..c64795cae1 100644
--- a/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using JsonApiDotNetCore.Internal;
 
 namespace JsonApiDotNetCore.Extensions
 {
@@ -62,6 +63,11 @@ public static IEnumerable<int> IndexesOf(this string str, char delimeter)
             }
             return indexes;
         }
+
+        public static SpanSplitter SpanSplit(this string str, char delimeter)
+        {
+            return SpanSplitter.Split(str, delimeter);
+        }
         
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
index 8602a24f30..6415b0c575 100644
--- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Linq;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
 
@@ -15,7 +16,7 @@ public RelatedAttrFilterQuery(
         {
             _jsonApiContext = jsonApiCopntext;
             var filterQueryAttribute = filterQuery.Attribute;
-            var filterQuerySubSpans = new SpanSplitter(ref filterQueryAttribute, '.');
+            var filterQuerySubSpans = filterQueryAttribute.SpanSplit('.');
             var subSpan1 = filterQuerySubSpans[0].ToString();
             var subSpan2 = filterQuerySubSpans[1].ToString();
             var relationship = GetRelationship(subSpan1);
diff --git a/src/JsonApiDotNetCore/Internal/SpanSplitter.cs b/src/JsonApiDotNetCore/Internal/SpanSplitter.cs
index 268bcab195..0f9aecbb59 100644
--- a/src/JsonApiDotNetCore/Internal/SpanSplitter.cs
+++ b/src/JsonApiDotNetCore/Internal/SpanSplitter.cs
@@ -15,7 +15,7 @@ public readonly ref struct SpanSplitter
         public int Count => _substringIndexes.Count();
         public ReadOnlySpan<char> this[int index] => GetSpanForSubstring(index + 1);
 
-        public SpanSplitter(ref string str, char delimeter)
+        private SpanSplitter(ref string str, char delimeter)
         {
             _span = str.AsSpan();
             _delimeterIndexes = str.IndexesOf(delimeter).ToList();
@@ -23,6 +23,11 @@ public SpanSplitter(ref string str, char delimeter)
             BuildSubstringIndexes();
         }
 
+        public static SpanSplitter Split(string str, char delimeter)
+        {
+            return new SpanSplitter(ref str, delimeter);
+        }
+
         [EditorBrowsable(EditorBrowsableState.Never)]
         public override bool Equals(object obj) => throw new NotSupportedException();
 
diff --git a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
index a7bbebb7f4..8b6111fef9 100644
--- a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
+++ b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Primitives;
@@ -56,7 +57,7 @@ private static bool IsValidAcceptHeader(HttpContext context)
         private static bool ContainsMediaTypeParameters(string mediaType)
         {
             const char delimeter = ';';
-            var subSpans = new SpanSplitter(ref mediaType, delimeter);
+            var subSpans = mediaType.SpanSplit(delimeter);
             if (subSpans.Count == 0) return false;
             return subSpans.Count == 2 && subSpans[0].ToString() == Constants.ContentType;
         }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 0f07624a4e..b45b68c97b 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -3,6 +3,7 @@
 using System.Linq;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
@@ -76,7 +77,7 @@ public IJsonApiContext ApplyContext<T>(object controller)
             BasePath = linkBuilder.GetBasePath(context, _controllerContext.RequestEntity.EntityName);
             PageManager = GetPageManager();
 
-            var pathSpans = new SpanSplitter(ref requestPath, '/');
+            var pathSpans = requestPath.SpanSplit('/');
             IsRelationshipPath = pathSpans[pathSpans.Count - 2].ToString() == "relationships";
 
             return this;
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index f988664c62..ddff31b5f1 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -99,7 +99,7 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
             var propertyNameSlice = key.AsSpan().Slice(openBracketIndex + 1, closedBracketIndex - openBracketIndex - 1);
             var propertyName = propertyNameSlice.ToString();
 
-            var spanSplitter = new SpanSplitter(ref value, COMMA);
+            var spanSplitter = value.SpanSplit(COMMA);
             for (var i = 0; i < spanSplitter.Count; i++)
             {
                 queries.Add(BuildFilterQuery(spanSplitter[i], propertyName));
diff --git a/test/UnitTests/Internal/SpanSplitterTests.cs b/test/UnitTests/Internal/SpanSplitterTests.cs
index 016ee8ec82..61160e7462 100644
--- a/test/UnitTests/Internal/SpanSplitterTests.cs
+++ b/test/UnitTests/Internal/SpanSplitterTests.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using Xunit;
 
@@ -88,7 +89,7 @@ protected void GivenStringWithCommaDelimeterAtBeginning()
         protected void WhenSplittingIntoSubstrings()
         {
             SpanSplitter spanSplitter;
-            spanSplitter = new SpanSplitter(ref _baseString, _delimeter);
+            spanSplitter = _baseString.SpanSplit(_delimeter);
             for (var i = 0; i < spanSplitter.Count; i++)
             {
                 var span = spanSplitter[i];

From 6fc48de9f017b56b6f474fcdc0ae7c978c2c235f Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Wed, 25 Apr 2018 14:13:03 -0500
Subject: [PATCH 140/227] Update README.md

---
 README.md | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/README.md b/README.md
index ae66e3a07c..2250ef4568 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,16 @@
 
 A framework for building [json:api](http://jsonapi.org/) compliant web APIs. The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination. You just need to focus on defining the resources and implementing your custom business logic. This library has been designed around dependency injection making extensibility incredibly easy.
 
+## Getting Started
+
+These are some steps you can take to help you understand what this project is and how you can use it:
+
+- [What is json:api and why should I use it?](https://nordicapis.com/the-benefits-of-using-json-api/)
+- [The json:api specification](http://jsonapi.org/format/)
+- [Demo [Video]](https://youtu.be/KAMuo6K7VcE)
+- [Our documentation](https://json-api-dotnet.github.io)
+- Check out the examples in the next section
+
 ## Examples
 
 See the [examples](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples) directory for up-to-date sample applications. There is also a [Todo List App](https://github.com/json-api-dotnet/TodoListExample) that includes a JADNC API and an EmberJs client.

From a7774b552ac51e4139403a7b4892aa78cff1acbe Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 28 Apr 2018 20:01:32 -0500
Subject: [PATCH 141/227] refactor(LinkBuilder): reduce allocations

---
 ...espaceFromPath_Benchmarks-report-github.md | 16 ++++
 ...uilder_ GetNamespaceFromPath_Benchmarks.cs | 90 +++++++++++++++++++
 benchmarks/Program.cs                         |  4 +-
 src/JsonApiDotNetCore/Builders/LinkBuilder.cs | 36 +++++---
 4 files changed, 134 insertions(+), 12 deletions(-)
 create mode 100644 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.LinkBuilder.LinkBuilder_GetNamespaceFromPath_Benchmarks-report-github.md
 create mode 100644 benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs

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
new file mode 100644
index 0000000000..72951396e8
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.LinkBuilder.LinkBuilder_GetNamespaceFromPath_Benchmarks-report-github.md
@@ -0,0 +1,16 @@
+``` 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/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs b/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs
new file mode 100644
index 0000000000..0604a68083
--- /dev/null
+++ b/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs	
@@ -0,0 +1,90 @@
+using System;
+using System.Diagnostics;
+using System.Text;
+using System.Threading;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Attributes.Exporters;
+using BenchmarkDotNet.Attributes.Jobs;
+using JsonApiDotNetCore.Extensions;
+
+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 UsingSpanWithStringBuilder() => GetNamespaceFromPath_Using_Span_With_StringBuilder(PATH, ENTITY_NAME);
+
+        [Benchmark]
+        public void UsingSpanWithNoAlloc() => GetNamespaceFromPath_Using_Span_No_Alloc(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 GetNamespaceFromPath_Using_Span_No_Alloc(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 + 1].Equals(delimiter))
+                            {
+                                return pathSpan.Slice(0, i).ToString();
+                            }
+                        }
+                    }
+                }
+            }
+
+            return string.Empty;
+        }
+
+        public static string GetNamespaceFromPath_Using_Span_With_StringBuilder(string path, string entityName)
+        {
+            var sb = new StringBuilder();
+            var entityNameSpan = entityName.AsSpan();
+            var subSpans = path.SpanSplit('/');
+            for (var i = 1; i < subSpans.Count; i++)
+            {
+                var span = subSpans[i];
+                if (entityNameSpan.SequenceEqual(span)) 
+                    break;
+
+                sb.Append($"/{span.ToString()}");
+            }
+            return sb.ToString();
+        }
+    }
+}
diff --git a/benchmarks/Program.cs b/benchmarks/Program.cs
index 7665d5fb97..813153ecb5 100644
--- a/benchmarks/Program.cs
+++ b/benchmarks/Program.cs
@@ -1,4 +1,5 @@
 using BenchmarkDotNet.Running;
+using Benchmarks.LinkBuilder;
 using Benchmarks.Query;
 using Benchmarks.Serialization;
 
@@ -8,7 +9,8 @@ static void Main(string[] args) {
             var switcher = new BenchmarkSwitcher(new[] {
                 typeof(JsonApiDeserializer_Benchmarks),
                 typeof(JsonApiSerializer_Benchmarks),
-                typeof(QueryParser_Benchmarks)
+                typeof(QueryParser_Benchmarks),
+                typeof(LinkBuilder_GetNamespaceFromPath_Benchmarks)
             });
             switcher.Run(args);
         }
diff --git a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
index b2bfcae168..9c3d19b05b 100644
--- a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
@@ -1,7 +1,4 @@
 using System;
-using System.Text;
-using JsonApiDotNetCore.Extensions;
-using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
 
@@ -20,22 +17,39 @@ public string GetBasePath(HttpContext context, string entityName)
         {
             var r = context.Request;
             return (_context.Options.RelativeLinks)
-                ? $"{GetNamespaceFromPath(r.Path, entityName)}"
+                ? GetNamespaceFromPath(r.Path, entityName)
                 : $"{r.Scheme}://{r.Host}{GetNamespaceFromPath(r.Path, entityName)}";
         }
 
         private static string GetNamespaceFromPath(string path, string entityName)
         {
-            var sb = new StringBuilder();
             var entityNameSpan = entityName.AsSpan();
-            var subSpans = path.SpanSplit('/');
-            for (var i = 1; i < subSpans.Count; i++)
+            var pathSpan = path.AsSpan();
+            const char delimiter = '/';
+            for (var i = 0; i < pathSpan.Length; i++)
             {
-                var span = subSpans[i];
-                if (entityNameSpan.SequenceEqual(span)) break;
-                sb.Append($"/{span.ToString()}");
+                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 sb.ToString();
+
+            return string.Empty;
         }
 
         public string GetSelfRelationLink(string parent, string parentId, string child)

From 8beb2e50fe38ca7d3cc3c0b0297512bee94b2ceb Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Tue, 1 May 2018 10:46:39 -0500
Subject: [PATCH 142/227] Update .travis.yml

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index b8a1d74643..7ac38bba9f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ services:
 before_script:
   - psql -c 'create database JsonApiDotNetCoreExample;' -U postgres
 mono: none
-dotnet: 2.0.3 # https://www.microsoft.com/net/download/linux
+dotnet: 2.1.105 # https://www.microsoft.com/net/download/linux
 branches:
   only:
     - master

From e3741253b852bd4bf385345e2b57844a95a2fb67 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 1 May 2018 20:33:00 -0500
Subject: [PATCH 143/227] benchamrk: don't duplicate the final version's
 definition

---
 ...uilder_ GetNamespaceFromPath_Benchmarks.cs | 36 ++-----------------
 src/JsonApiDotNetCore/Builders/LinkBuilder.cs |  2 +-
 2 files changed, 4 insertions(+), 34 deletions(-)

diff --git a/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs b/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs
index 0604a68083..d53294e749 100644
--- a/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs	
+++ b/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs	
@@ -1,7 +1,5 @@
 using System;
-using System.Diagnostics;
 using System.Text;
-using System.Threading;
 using BenchmarkDotNet.Attributes;
 using BenchmarkDotNet.Attributes.Exporters;
 using BenchmarkDotNet.Attributes.Jobs;
@@ -22,7 +20,7 @@ public class LinkBuilder_GetNamespaceFromPath_Benchmarks
         public void UsingSpanWithStringBuilder() => GetNamespaceFromPath_Using_Span_With_StringBuilder(PATH, ENTITY_NAME);
 
         [Benchmark]
-        public void UsingSpanWithNoAlloc() => GetNamespaceFromPath_Using_Span_No_Alloc(PATH, ENTITY_NAME);
+        public void Current() => GetNameSpaceFromPath_Current(PATH, ENTITY_NAME);
 
         public static string GetNamespaceFromPath_BySplitting(string path, string entityName)
         {
@@ -40,36 +38,8 @@ public static string GetNamespaceFromPath_BySplitting(string path, string entity
             return nSpace;
         }
 
-        public static string GetNamespaceFromPath_Using_Span_No_Alloc(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 + 1].Equals(delimiter))
-                            {
-                                return pathSpan.Slice(0, i).ToString();
-                            }
-                        }
-                    }
-                }
-            }
-
-            return string.Empty;
-        }
+        public static string GetNameSpaceFromPath_Current(string path, string entityName)
+            => JsonApiDotNetCore.Builders.LinkBuilder.GetNamespaceFromPath(path, entityName);
 
         public static string GetNamespaceFromPath_Using_Span_With_StringBuilder(string path, string entityName)
         {
diff --git a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
index 9c3d19b05b..c3769eccbc 100644
--- a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
@@ -21,7 +21,7 @@ public string GetBasePath(HttpContext context, string entityName)
                 : $"{r.Scheme}://{r.Host}{GetNamespaceFromPath(r.Path, entityName)}";
         }
 
-        private static string GetNamespaceFromPath(string path, string entityName)
+        internal static string GetNamespaceFromPath(string path, string entityName)
         {
             var entityNameSpan = entityName.AsSpan();
             var pathSpan = path.AsSpan();

From b647f94ab037624d359f59ea0ba905cc47e104ea Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 1 May 2018 21:26:19 -0500
Subject: [PATCH 144/227] add benchmarks to RequestMiddleware

---
 ...TypeParameters_Benchmarks-report-github.md | 14 ++++++++++
 benchmarks/Program.cs                         |  4 ++-
 .../ContainsMediaTypeParameters_Benchmarks.cs | 26 +++++++++++++++++++
 .../Middleware/RequestMiddleware.cs           | 22 +++++++++++-----
 4 files changed, 59 insertions(+), 7 deletions(-)
 create mode 100644 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.RequestMiddleware.ContainsMediaTypeParameters_Benchmarks-report-github.md
 create mode 100644 benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs

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
new file mode 100644
index 0000000000..066e7b2036
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.RequestMiddleware.ContainsMediaTypeParameters_Benchmarks-report-github.md
@@ -0,0 +1,14 @@
+``` 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/Program.cs b/benchmarks/Program.cs
index 813153ecb5..989272c7f1 100644
--- a/benchmarks/Program.cs
+++ b/benchmarks/Program.cs
@@ -1,6 +1,7 @@
 using BenchmarkDotNet.Running;
 using Benchmarks.LinkBuilder;
 using Benchmarks.Query;
+using Benchmarks.RequestMiddleware;
 using Benchmarks.Serialization;
 
 namespace Benchmarks {
@@ -10,7 +11,8 @@ static void Main(string[] args) {
                 typeof(JsonApiDeserializer_Benchmarks),
                 typeof(JsonApiSerializer_Benchmarks),
                 typeof(QueryParser_Benchmarks),
-                typeof(LinkBuilder_GetNamespaceFromPath_Benchmarks)
+                typeof(LinkBuilder_GetNamespaceFromPath_Benchmarks),
+                typeof(ContainsMediaTypeParameters_Benchmarks)
             });
             switcher.Run(args);
         }
diff --git a/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs b/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs
new file mode 100644
index 0000000000..9826bd158a
--- /dev/null
+++ b/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs
@@ -0,0 +1,26 @@
+using System;
+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.RequestMiddleware.ContainsMediaTypeParameters(MEDIA_TYPE);
+
+        private bool UsingSplitImpl(string mediaType)
+        {
+            var mediaTypeArr = mediaType.Split(';');
+            return (mediaTypeArr[0] ==  Constants.ContentType && mediaTypeArr.Length == 2);	
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
index 8b6111fef9..0ce54c8589 100644
--- a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
+++ b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Threading.Tasks;
-using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Primitives;
@@ -54,12 +53,23 @@ private static bool IsValidAcceptHeader(HttpContext context)
             return true;
         }
 
-        private static bool ContainsMediaTypeParameters(string mediaType)
+        internal static bool ContainsMediaTypeParameters(string mediaType)
         {
-            const char delimeter = ';';
-            var subSpans = mediaType.SpanSplit(delimeter);
-            if (subSpans.Count == 0) return false;
-            return subSpans.Count == 2 && subSpans[0].ToString() == Constants.ContentType;
+            var incomingMediaTypeSpan = mediaType.AsSpan();
+
+            // if the content type is not application/vnd.api+json then continue on
+            if(incomingMediaTypeSpan.Length < Constants.ContentType.Length)
+                return false;
+
+            var incomingContentType = incomingMediaTypeSpan.Slice(0, Constants.ContentType.Length);
+            if(incomingContentType.SequenceEqual(Constants.ContentType.AsSpan()) == false)
+                return false;
+
+            // anything appended to "application/vnd.api+json;" will be considered a media type param
+            return (
+                incomingMediaTypeSpan.Length >= Constants.ContentType.Length + 2
+                && incomingMediaTypeSpan[Constants.ContentType.Length] == ';'
+            );
         }
 
         private static void FlushResponse(HttpContext context, int statusCode)

From 0f4ccf660d97d14bffae2fe346ba7216ef3611ac Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 1 May 2018 22:24:57 -0500
Subject: [PATCH 145/227] add benchmarks for IsRelationshipPath

---
 ...IsRelationship_Benchmarks-report-github.md | 12 +++++
 .../PathIsRelationship_Benchmarks.cs          | 24 ++++++++++
 benchmarks/Program.cs                         |  4 +-
 .../ContainsMediaTypeParameters_Benchmarks.cs |  1 -
 .../Services/JsonApiContext.cs                | 44 +++++++++++++++----
 5 files changed, 75 insertions(+), 10 deletions(-)
 create mode 100644 benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.JsonApiContext.PathIsRelationship_Benchmarks-report-github.md
 create mode 100644 benchmarks/JsonApiContext/PathIsRelationship_Benchmarks.cs

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
new file mode 100644
index 0000000000..6be58e241a
--- /dev/null
+++ b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.JsonApiContext.PathIsRelationship_Benchmarks-report-github.md
@@ -0,0 +1,12 @@
+```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/JsonApiContext/PathIsRelationship_Benchmarks.cs b/benchmarks/JsonApiContext/PathIsRelationship_Benchmarks.cs
new file mode 100644
index 0000000000..83fe6fc53c
--- /dev/null
+++ b/benchmarks/JsonApiContext/PathIsRelationship_Benchmarks.cs
@@ -0,0 +1,24 @@
+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/Program.cs b/benchmarks/Program.cs
index 989272c7f1..9a2c45dffb 100644
--- a/benchmarks/Program.cs
+++ b/benchmarks/Program.cs
@@ -1,4 +1,5 @@
 using BenchmarkDotNet.Running;
+using Benchmarks.JsonApiContext;
 using Benchmarks.LinkBuilder;
 using Benchmarks.Query;
 using Benchmarks.RequestMiddleware;
@@ -12,7 +13,8 @@ static void Main(string[] args) {
                 typeof(JsonApiSerializer_Benchmarks),
                 typeof(QueryParser_Benchmarks),
                 typeof(LinkBuilder_GetNamespaceFromPath_Benchmarks),
-                typeof(ContainsMediaTypeParameters_Benchmarks)
+                typeof(ContainsMediaTypeParameters_Benchmarks),
+                typeof(PathIsRelationship_Benchmarks)
             });
             switcher.Run(args);
         }
diff --git a/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs b/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs
index 9826bd158a..ed64c98335 100644
--- a/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs
+++ b/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs
@@ -1,4 +1,3 @@
-using System;
 using BenchmarkDotNet.Attributes;
 using BenchmarkDotNet.Attributes.Exporters;
 using JsonApiDotNetCore.Internal;
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index b45b68c97b..2665217fef 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -1,9 +1,7 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
@@ -65,7 +63,6 @@ public IJsonApiContext ApplyContext<T>(object controller)
                 throw new JsonApiException(500, $"A resource has not been properly defined for type '{typeof(T)}'. Ensure it has been registered on the ContextGraph.");
 
             var context = _httpContextAccessor.HttpContext;
-            var requestPath = context.Request.Path.Value;
 
             if (context.Request.Query.Count > 0)
             {
@@ -73,15 +70,46 @@ public IJsonApiContext ApplyContext<T>(object controller)
                 IncludedRelationships = QuerySet.IncludedRelationships;
             }
 
-            var linkBuilder = new LinkBuilder(this);
-            BasePath = linkBuilder.GetBasePath(context, _controllerContext.RequestEntity.EntityName);
+            BasePath = new LinkBuilder(this).GetBasePath(context, _controllerContext.RequestEntity.EntityName);
             PageManager = GetPageManager();
-
-            var pathSpans = requestPath.SpanSplit('/');
-            IsRelationshipPath = pathSpans[pathSpans.Count - 2].ToString() == "relationships";
+            IsRelationshipPath = PathIsRelationship(context.Request.Path.Value);
 
             return this;
         }
+
+        internal static bool PathIsRelationship(string requestPath)
+        {
+            // while(!Debugger.IsAttached) { Thread.Sleep(1000); }
+            const string relationships = "relationships";
+            const char pathSegmentDelimiter = '/';
+
+            var span = requestPath.AsSpan();
+            
+            // we need to iterate over the string, from the end,
+            // checking whether or not the 2nd to last path segment
+            // is "relationships"
+            // -2 is chosen in case the path ends with '/'
+            for(var i = requestPath.Length - 2; i >= 0; i--)
+            {
+                // if there are not enough characters left in the path to 
+                // contain "relationships"
+                if(i < relationships.Length) 
+                    return false;
+
+                // we have found the first instance of '/'
+                if(span[i] == pathSegmentDelimiter)
+                {
+                    // in the case of a "relationships" route, the next
+                    // path segment will be "relationships"
+                    return (
+                        span.Slice(i - relationships.Length, relationships.Length)
+                            .SequenceEqual(relationships.AsSpan())
+                    );
+                }
+            }
+
+            return false;
+        }
         
         private PageManager GetPageManager()
         {

From d94287ef0cf9b786140a5ba483e134dd122d12d6 Mon Sep 17 00:00:00 2001
From: Jacob Hilty <jacob.hilty@kalibrate.com>
Date: Fri, 4 May 2018 13:16:56 -0400
Subject: [PATCH 146/227] Closes #273

---
 src/JsonApiDotNetCore/Builders/LinkBuilder.cs |  4 +-
 .../Internal/Query/QueryConstants.cs          | 15 +++++
 .../Services/QueryComposer.cs                 | 38 +++++++++++++
 src/JsonApiDotNetCore/Services/QueryParser.cs | 39 +++++--------
 .../Spec/DocumentTests/PagingTests.cs         |  1 +
 test/UnitTests/Services/QueryComposerTests.cs | 57 +++++++++++++++++++
 6 files changed, 128 insertions(+), 26 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Internal/Query/QueryConstants.cs
 create mode 100644 src/JsonApiDotNetCore/Services/QueryComposer.cs
 create mode 100644 test/UnitTests/Services/QueryComposerTests.cs

diff --git a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
index dced1225a9..42b82e6255 100644
--- a/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/LinkBuilder.cs
@@ -48,7 +48,9 @@ public string GetRelatedRelationLink(string parent, string parentId, string chil
 
         public string GetPageLink(int pageOffset, int pageSize)
         {
-            return $"{_context.BasePath}/{_context.RequestEntity.EntityName}?page[size]={pageSize}&page[number]={pageOffset}";
+            var filterQueryComposer = new QueryComposer();
+            var filters = filterQueryComposer.Compose(_context);
+            return $"{_context.BasePath}/{_context.RequestEntity.EntityName}?page[size]={pageSize}&page[number]={pageOffset}{filters}";
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Query/QueryConstants.cs b/src/JsonApiDotNetCore/Internal/Query/QueryConstants.cs
new file mode 100644
index 0000000000..3117ff7cb3
--- /dev/null
+++ b/src/JsonApiDotNetCore/Internal/Query/QueryConstants.cs
@@ -0,0 +1,15 @@
+namespace JsonApiDotNetCore.Internal.Query{
+    public static class QueryConstants {
+        public const string FILTER = "filter";
+        public const string SORT = "sort";
+        public const string INCLUDE = "include";
+        public const string PAGE = "page";
+        public const string FIELDS = "fields";
+        public const char OPEN_BRACKET = '[';
+        public const char CLOSE_BRACKET = ']';
+        public const char COMMA = ',';
+        public const char COLON = ':';
+        public const string COLON_STR = ":";
+
+    }
+}
\ No newline at end of file
diff --git a/src/JsonApiDotNetCore/Services/QueryComposer.cs b/src/JsonApiDotNetCore/Services/QueryComposer.cs
new file mode 100644
index 0000000000..8fbf16339b
--- /dev/null
+++ b/src/JsonApiDotNetCore/Services/QueryComposer.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+using JsonApiDotNetCore.Internal.Query;
+using Microsoft.Extensions.Logging;
+
+namespace JsonApiDotNetCore.Services
+{
+    public interface IQueryComposer
+    {
+        string Compose(IJsonApiContext jsonApiContext);
+    }
+
+    public class QueryComposer : IQueryComposer
+    {
+        public string Compose(IJsonApiContext jsonApiContext)
+        {
+            string result = "";
+            if(jsonApiContext != null && jsonApiContext.QuerySet != null)
+            {                
+                List<FilterQuery> filterQueries = jsonApiContext.QuerySet.Filters;
+                if (filterQueries.Count > 0)
+                {
+                    foreach (FilterQuery filter in filterQueries)
+                    {
+                        result += ComposeSingleFilter(filter);
+                    }
+                }
+            }
+            return result;
+        }
+
+        private string ComposeSingleFilter(FilterQuery query)
+        {
+            var result = "&filter";
+            result += QueryConstants.OPEN_BRACKET + query.Attribute + QueryConstants.CLOSE_BRACKET + query.Operation + query.Value;
+            return result;
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 5e705f4bc9..d7ac2d90bf 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -20,17 +20,6 @@ public class QueryParser : IQueryParser
         private readonly IControllerContext _controllerContext;
         private readonly JsonApiOptions _options;
 
-        private const string FILTER = "filter";
-        private const string SORT = "sort";
-        private const string INCLUDE = "include";
-        private const string PAGE = "page";
-        private const string FIELDS = "fields";
-        private const char OPEN_BRACKET = '[';
-        private const char CLOSE_BRACKET = ']';
-        private const char COMMA = ',';
-        private const char COLON = ':';
-        private const string COLON_STR = ":";
-
         public QueryParser(
             IControllerContext controllerContext,
             JsonApiOptions options)
@@ -46,35 +35,35 @@ public virtual QuerySet Parse(IQueryCollection query)
 
             foreach (var pair in query)
             {
-                if (pair.Key.StartsWith(FILTER))
+                if (pair.Key.StartsWith(QueryConstants.FILTER))
                 {
                     if (disabledQueries.HasFlag(QueryParams.Filter) == false)
                         querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value));
                     continue;
                 }
 
-                if (pair.Key.StartsWith(SORT))
+                if (pair.Key.StartsWith(QueryConstants.SORT))
                 {
                     if (disabledQueries.HasFlag(QueryParams.Sort) == false)
                         querySet.SortParameters = ParseSortParameters(pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith(INCLUDE))
+                if (pair.Key.StartsWith(QueryConstants.INCLUDE))
                 {
                     if (disabledQueries.HasFlag(QueryParams.Include) == false)
                         querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith(PAGE))
+                if (pair.Key.StartsWith(QueryConstants.PAGE))
                 {
                     if (disabledQueries.HasFlag(QueryParams.Page) == false)
                         querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value);
                     continue;
                 }
 
-                if (pair.Key.StartsWith(FIELDS))
+                if (pair.Key.StartsWith(QueryConstants.FIELDS))
                 {
                     if (disabledQueries.HasFlag(QueryParams.Fields) == false)
                         querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value);
@@ -94,9 +83,9 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
             // expected input = filter[id]=eq:1
             var queries = new List<FilterQuery>();
 
-            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
+            var propertyName = key.Split(QueryConstants.OPEN_BRACKET, QueryConstants.CLOSE_BRACKET)[1];
 
-            var values = value.Split(COMMA);
+            var values = value.Split(QueryConstants.COMMA);
             foreach (var val in values)
             {
                 (var operation, var filterValue) = ParseFilterOperation(val);
@@ -111,7 +100,7 @@ protected virtual (string operation, string value) ParseFilterOperation(string v
             if (value.Length < 3)
                 return (string.Empty, value);
 
-            var operation = value.Split(COLON);
+            var operation = value.Split(QueryConstants.COLON);
 
             if (operation.Length == 1)
                 return (string.Empty, value);
@@ -121,7 +110,7 @@ protected virtual (string operation, string value) ParseFilterOperation(string v
                 return (string.Empty, value);
 
             var prefix = operation[0];
-            value = string.Join(COLON_STR, operation.Skip(1));
+            value = string.Join(QueryConstants.COLON_STR, operation.Skip(1));
 
             return (prefix, value);
         }
@@ -132,7 +121,7 @@ protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, stri
             //                  page[number]=1
             pageQuery = pageQuery ?? new PageQuery();
 
-            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
+            var propertyName = key.Split(QueryConstants.OPEN_BRACKET, QueryConstants.CLOSE_BRACKET)[1];
 
             const string SIZE = "size";
             const string NUMBER = "number";
@@ -157,7 +146,7 @@ protected virtual List<SortQuery> ParseSortParameters(string value)
             var sortParameters = new List<SortQuery>();
 
             const char DESCENDING_SORT_OPERATOR = '-';
-            var sortSegments = value.Split(COMMA);
+            var sortSegments = value.Split(QueryConstants.COMMA);
 
             foreach (var sortSegment in sortSegments)
             {
@@ -189,14 +178,14 @@ protected virtual List<string> ParseIncludedRelationships(string value)
                 throw new JsonApiException(400, "Deeply nested relationships are not supported");
 
             return value
-                .Split(COMMA)
+                .Split(QueryConstants.COMMA)
                 .ToList();
         }
 
         protected virtual List<string> ParseFieldsQuery(string key, string value)
         {
             // expected: fields[TYPE]=prop1,prop2
-            var typeName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
+            var typeName = key.Split(QueryConstants.OPEN_BRACKET, QueryConstants.CLOSE_BRACKET)[1];
 
             const string ID = "Id";
             var includedFields = new List<string> { ID };
@@ -205,7 +194,7 @@ protected virtual List<string> ParseFieldsQuery(string key, string value)
             if (string.Equals(typeName, _controllerContext.RequestEntity.EntityName, StringComparison.OrdinalIgnoreCase) == false)
                 return includedFields;
 
-            var fields = value.Split(COMMA);
+            var fields = value.Split(QueryConstants.COMMA);
             foreach (var field in fields)
             {
                 var attr = _controllerContext.RequestEntity
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
index 787c9f07a0..faae94a3d8 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
@@ -23,6 +23,7 @@ public class PagingTests
         private Faker<Person> _personFaker;
         private Faker<TodoItem> _todoItemFaker;
         private Faker<TodoItemCollection> _todoItemCollectionFaker;
+        private DateTime CurrentTime;
 
         public PagingTests(TestFixture<TestStartup> fixture)
         {
diff --git a/test/UnitTests/Services/QueryComposerTests.cs b/test/UnitTests/Services/QueryComposerTests.cs
new file mode 100644
index 0000000000..e1bd892756
--- /dev/null
+++ b/test/UnitTests/Services/QueryComposerTests.cs
@@ -0,0 +1,57 @@
+using System.Collections.Generic;
+using JsonApiDotNetCore.Internal.Query;
+using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Http;
+using Moq;
+using Xunit;
+
+namespace UnitTests.Services
+{
+    public class QueryComposerTests
+    {
+        private readonly Mock<IJsonApiContext> _jsonApiContext;
+
+        public QueryComposerTests()
+        {
+            _jsonApiContext = new Mock<IJsonApiContext>();
+        }
+
+        [Fact]
+        public void Can_Compose_FilterStringForUrl()
+        {
+            // arrange
+            var filter = new FilterQuery("attribute", "value", "=");
+            var querySet = new QuerySet();
+            List<FilterQuery> filters = new List<FilterQuery>();
+            filters.Add(filter);
+            querySet.Filters=filters;
+
+            _jsonApiContext
+                .Setup(m => m.QuerySet)
+                .Returns(querySet);
+
+            var queryComposer = new QueryComposer();
+            // act
+            var filterString = queryComposer.Compose(_jsonApiContext.Object);
+            // assert
+            Assert.Equal("&filter[attribute]=value", filterString);
+        }
+
+        [Fact]
+        public void NoFilter_Compose_EmptyStringReturned()
+        {
+            // arrange
+            var querySet = new QuerySet();
+
+            _jsonApiContext
+                .Setup(m => m.QuerySet)
+                .Returns(querySet);
+
+            var queryComposer = new QueryComposer();
+            // act
+            var filterString = queryComposer.Compose(_jsonApiContext.Object);
+            // assert
+            Assert.Equal("", filterString); 
+        }
+    }
+}
\ No newline at end of file

From ca7c4ea8457911da50e8f9396a16be10335c80bc Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 6 May 2018 16:56:19 -0500
Subject: [PATCH 147/227] clean up unused changes

---
 ...uilder_ GetNamespaceFromPath_Benchmarks.cs |  22 ----
 .../Extensions/StringExtensions.cs            |  19 ---
 .../Internal/Query/RelatedAttrFilterQuery.cs  |  17 ++-
 .../Internal/SpanSplitter.cs                  |  69 -----------
 src/JsonApiDotNetCore/Services/QueryParser.cs |  15 ++-
 test/UnitTests/Internal/SpanSplitterTests.cs  | 108 ------------------
 6 files changed, 14 insertions(+), 236 deletions(-)
 delete mode 100644 src/JsonApiDotNetCore/Internal/SpanSplitter.cs
 delete mode 100644 test/UnitTests/Internal/SpanSplitterTests.cs

diff --git a/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs b/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs
index d53294e749..05728321c3 100644
--- a/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs	
+++ b/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs	
@@ -1,9 +1,6 @@
-using System;
-using System.Text;
 using BenchmarkDotNet.Attributes;
 using BenchmarkDotNet.Attributes.Exporters;
 using BenchmarkDotNet.Attributes.Jobs;
-using JsonApiDotNetCore.Extensions;
 
 namespace Benchmarks.LinkBuilder
 {
@@ -16,9 +13,6 @@ public class LinkBuilder_GetNamespaceFromPath_Benchmarks
         [Benchmark]
         public void UsingSplit() => GetNamespaceFromPath_BySplitting(PATH, ENTITY_NAME);
 
-        [Benchmark]
-        public void UsingSpanWithStringBuilder() => GetNamespaceFromPath_Using_Span_With_StringBuilder(PATH, ENTITY_NAME);
-
         [Benchmark]
         public void Current() => GetNameSpaceFromPath_Current(PATH, ENTITY_NAME);
 
@@ -40,21 +34,5 @@ public static string GetNamespaceFromPath_BySplitting(string path, string entity
 
         public static string GetNameSpaceFromPath_Current(string path, string entityName)
             => JsonApiDotNetCore.Builders.LinkBuilder.GetNamespaceFromPath(path, entityName);
-
-        public static string GetNamespaceFromPath_Using_Span_With_StringBuilder(string path, string entityName)
-        {
-            var sb = new StringBuilder();
-            var entityNameSpan = entityName.AsSpan();
-            var subSpans = path.SpanSplit('/');
-            for (var i = 1; i < subSpans.Count; i++)
-            {
-                var span = subSpans[i];
-                if (entityNameSpan.SequenceEqual(span)) 
-                    break;
-
-                sb.Append($"/{span.ToString()}");
-            }
-            return sb.ToString();
-        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Extensions/StringExtensions.cs b/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
index c64795cae1..24d5bc8d58 100644
--- a/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/StringExtensions.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
 using System.Text;
-using JsonApiDotNetCore.Internal;
 
 namespace JsonApiDotNetCore.Extensions
 {
@@ -53,21 +50,5 @@ public static string Dasherize(this string str)
             }
             return str;
         }
-
-        public static IEnumerable<int> IndexesOf(this string str, char delimeter)
-        {
-            var indexes = new List<int>();
-            for (var i = str.IndexOf(delimeter); i > -1 ; i = str.IndexOf(delimeter, i+1))
-            {
-                indexes.Add(i);
-            }
-            return indexes;
-        }
-
-        public static SpanSplitter SpanSplit(this string str, char delimeter)
-        {
-            return SpanSplitter.Split(str, delimeter);
-        }
-        
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
index 6415b0c575..d567de200a 100644
--- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
@@ -11,20 +11,17 @@ public class RelatedAttrFilterQuery : BaseFilterQuery
         private readonly IJsonApiContext _jsonApiContext;
         
         public RelatedAttrFilterQuery(
-            IJsonApiContext jsonApiCopntext,
+            IJsonApiContext jsonApiContext,
             FilterQuery filterQuery)
         {
-            _jsonApiContext = jsonApiCopntext;
-            var filterQueryAttribute = filterQuery.Attribute;
-            var filterQuerySubSpans = filterQueryAttribute.SpanSplit('.');
-            var subSpan1 = filterQuerySubSpans[0].ToString();
-            var subSpan2 = filterQuerySubSpans[1].ToString();
-            var relationship = GetRelationship(subSpan1);
-            if (relationship == null)
-                throw new JsonApiException(400, $"{subSpan2} is not a valid relationship on {subSpan1}.");
+            _jsonApiContext = jsonApiContext;
 
-            var attribute = GetAttribute(relationship, subSpan2);
+            var relationshipArray = filterQuery.Attribute.Split('.');
+            var relationship = GetRelationship(relationshipArray[0]);
+            if (relationship == null)
+                throw new JsonApiException(400, $"{relationshipArray[1]} is not a valid relationship on {relationshipArray[0]}.");
 
+            var attribute = GetAttribute(relationship, relationshipArray[1]);
             if (attribute == null)
                 throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute.");
 
diff --git a/src/JsonApiDotNetCore/Internal/SpanSplitter.cs b/src/JsonApiDotNetCore/Internal/SpanSplitter.cs
deleted file mode 100644
index 0f9aecbb59..0000000000
--- a/src/JsonApiDotNetCore/Internal/SpanSplitter.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using JsonApiDotNetCore.Extensions;
-
-namespace JsonApiDotNetCore.Internal
-{
-    public readonly ref struct SpanSplitter
-    {
-        private readonly ReadOnlySpan<char> _span;
-        private readonly List<int> _delimeterIndexes;
-        private readonly List<Tuple<int, int>> _substringIndexes;
-
-        public int Count => _substringIndexes.Count();
-        public ReadOnlySpan<char> this[int index] => GetSpanForSubstring(index + 1);
-
-        private SpanSplitter(ref string str, char delimeter)
-        {
-            _span = str.AsSpan();
-            _delimeterIndexes = str.IndexesOf(delimeter).ToList();
-            _substringIndexes = new List<Tuple<int, int>>();
-            BuildSubstringIndexes();
-        }
-
-        public static SpanSplitter Split(string str, char delimeter)
-        {
-            return new SpanSplitter(ref str, delimeter);
-        }
-
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override bool Equals(object obj) => throw new NotSupportedException();
-
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override int GetHashCode() => throw new NotSupportedException();
-
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override string ToString() => throw new NotSupportedException();
-
-        private ReadOnlySpan<char> GetSpanForSubstring(int substringNumber)
-        {
-            if (substringNumber > Count)
-            {
-                throw new ArgumentOutOfRangeException($"There are only {Count} substrings given the delimeter and base string provided");
-            }
-
-            var indexes = _substringIndexes[substringNumber - 1];
-            return _span.Slice(indexes.Item1, indexes.Item2);
-        }
-        
-        private void BuildSubstringIndexes()
-        {
-            var start = 0;
-            var end = 0;
-            foreach (var index in _delimeterIndexes)
-            {
-                end = index;
-                if (start > end) break;
-                _substringIndexes.Add(new Tuple<int, int>(start, end - start));
-                start = ++end;
-            }
-
-            if (end <= _span.Length)
-            {
-                _substringIndexes.Add(new Tuple<int, int>(start, _span.Length - start));
-            }
-        }
-    }
-}
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index ddff31b5f1..34bf525e8e 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -3,7 +3,6 @@
 using System.Linq;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Controllers;
-using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
@@ -94,16 +93,16 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
             // expected input = filter[id]=1
             // expected input = filter[id]=eq:1
             var queries = new List<FilterQuery>();
-            var openBracketIndex = key.IndexOf(OPEN_BRACKET);
-            var closedBracketIndex = key.IndexOf(CLOSE_BRACKET);
-            var propertyNameSlice = key.AsSpan().Slice(openBracketIndex + 1, closedBracketIndex - openBracketIndex - 1);
-            var propertyName = propertyNameSlice.ToString();
 
-            var spanSplitter = value.SpanSplit(COMMA);
-            for (var i = 0; i < spanSplitter.Count; i++)
+            var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1];
+
+            var values = value.Split(COMMA);
+            foreach (var val in values)
             {
-                queries.Add(BuildFilterQuery(spanSplitter[i], propertyName));
+                (var operation, var filterValue) = ParseFilterOperation(val);
+                queries.Add(new FilterQuery(propertyName, filterValue, operation));
             }
+
             return queries;
         }
 
diff --git a/test/UnitTests/Internal/SpanSplitterTests.cs b/test/UnitTests/Internal/SpanSplitterTests.cs
deleted file mode 100644
index 61160e7462..0000000000
--- a/test/UnitTests/Internal/SpanSplitterTests.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using JsonApiDotNetCore.Extensions;
-using JsonApiDotNetCore.Internal;
-using Xunit;
-
-namespace UnitTests.Internal
-{
-    public class SpanSplitterTests : SpanSplitterTestsBase
-    {
-        [Fact]
-        public void StringWithDelimeterSplitsIntoCorrectNumberSubstrings()
-        {
-            GivenMultipleCommaDelimetedString();
-            WhenSplittingIntoSubstrings();
-            AssertCorrectSubstringsReturned();
-        }
-
-        [Fact]
-        public void StringWithSingleDelimeterSplitsIntoCorrectNumberSubstrings()
-        {
-            GivenSingleCommaDelimetedString();
-            WhenSplittingIntoSubstrings();
-            AssertCorrectSubstringsReturned();
-        }
-
-        [Fact]
-        public void StringWithNoDelimeterSplitsIntoSingleSubstring()
-        {
-            GivenNonCommaDelimetedString();
-            WhenSplittingIntoSubstrings();
-            AssertCorrectSubstringsReturned();
-        }
-
-        [Fact]
-        public void StringWithDelimeterAtEndSplitsIntoCorrectSubstring()
-        {
-            GivenStringWithCommaDelimeterAtEnd();
-            WhenSplittingIntoSubstrings();
-            AssertCorrectSubstringsReturned();
-        }
-
-        [Fact]
-        public void StringWithDelimeterAtBeginningSplitsIntoCorrectSubstring()
-        {
-            GivenStringWithCommaDelimeterAtBeginning();
-            WhenSplittingIntoSubstrings();
-            AssertCorrectSubstringsReturned();
-        }
-    }
-
-    public abstract class SpanSplitterTestsBase
-    {
-        private string _baseString;
-        private char _delimeter;
-        private readonly List<string> _substrings = new List<string>();
-
-        protected void GivenMultipleCommaDelimetedString()
-        {
-            _baseString = "This,Is,A,TestString";
-            _delimeter = ',';
-        }
-
-        protected void GivenSingleCommaDelimetedString()
-        {
-            _baseString = "This,IsATestString";
-            _delimeter = ',';
-        }
-
-        protected void GivenNonCommaDelimetedString()
-        {
-            _baseString = "ThisIsATestString";
-        }
-
-        protected void GivenStringWithCommaDelimeterAtEnd()
-        {
-            _baseString = "This,IsATestString,";
-            _delimeter = ',';
-        }
-
-        protected void GivenStringWithCommaDelimeterAtBeginning()
-        {
-            _baseString = "/api/v1/articles";
-            _delimeter = '/';
-        }
-
-        protected void WhenSplittingIntoSubstrings()
-        {
-            SpanSplitter spanSplitter;
-            spanSplitter = _baseString.SpanSplit(_delimeter);
-            for (var i = 0; i < spanSplitter.Count; i++)
-            {
-                var span = spanSplitter[i];
-                _substrings.Add(span.ToString());
-            }
-        }
-
-        protected void AssertCorrectSubstringsReturned()
-        {
-            Assert.NotEmpty(_substrings);
-            var stringSplitArray = _baseString.Split(_delimeter);
-            Assert.Equal(stringSplitArray.Length, _substrings.Count);
-            Assert.True(stringSplitArray.SequenceEqual(_substrings));
-        }
-    }
-}

From 0332870cc5baf64b367e13b60e5b7c9479df47fb Mon Sep 17 00:00:00 2001
From: Faraz Ahmed <Farazuddin.Ahmed@kalibrate.com>
Date: Mon, 7 May 2018 15:12:06 -0400
Subject: [PATCH 148/227] added changes for fix and fixed tests

---
 .../Services/QueryComposer.cs                 |  2 +-
 test/UnitTests/Services/QueryComposerTests.cs | 29 ++++++++++++++++---
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/QueryComposer.cs b/src/JsonApiDotNetCore/Services/QueryComposer.cs
index 8fbf16339b..9747f6d47d 100644
--- a/src/JsonApiDotNetCore/Services/QueryComposer.cs
+++ b/src/JsonApiDotNetCore/Services/QueryComposer.cs
@@ -31,7 +31,7 @@ public string Compose(IJsonApiContext jsonApiContext)
         private string ComposeSingleFilter(FilterQuery query)
         {
             var result = "&filter";
-            result += QueryConstants.OPEN_BRACKET + query.Attribute + QueryConstants.CLOSE_BRACKET + query.Operation + query.Value;
+            result += QueryConstants.OPEN_BRACKET + query.Attribute + QueryConstants.CLOSE_BRACKET + "=" + query.Operation + ":" + query.Value;
             return result;
         }
     }
diff --git a/test/UnitTests/Services/QueryComposerTests.cs b/test/UnitTests/Services/QueryComposerTests.cs
index e1bd892756..cf54d10a5a 100644
--- a/test/UnitTests/Services/QueryComposerTests.cs
+++ b/test/UnitTests/Services/QueryComposerTests.cs
@@ -17,10 +17,10 @@ public QueryComposerTests()
         }
 
         [Fact]
-        public void Can_Compose_FilterStringForUrl()
+        public void Can_ComposeEqual_FilterStringForUrl()
         {
             // arrange
-            var filter = new FilterQuery("attribute", "value", "=");
+            var filter = new FilterQuery("attribute", "value", "eq");
             var querySet = new QuerySet();
             List<FilterQuery> filters = new List<FilterQuery>();
             filters.Add(filter);
@@ -34,7 +34,28 @@ public void Can_Compose_FilterStringForUrl()
             // act
             var filterString = queryComposer.Compose(_jsonApiContext.Object);
             // assert
-            Assert.Equal("&filter[attribute]=value", filterString);
+            Assert.Equal("&filter[attribute]=eq:value", filterString);
+        }
+
+        [Fact]
+        public void Can_ComposeLessThan_FilterStringForUrl()
+        {
+            // arrange
+            var filter = new FilterQuery("attribute", "value", "le");
+            var querySet = new QuerySet();
+            List<FilterQuery> filters = new List<FilterQuery>();
+            filters.Add(filter);
+            querySet.Filters = filters;
+
+            _jsonApiContext
+                .Setup(m => m.QuerySet)
+                .Returns(querySet);
+
+            var queryComposer = new QueryComposer();
+            // act
+            var filterString = queryComposer.Compose(_jsonApiContext.Object);
+            // assert
+            Assert.Equal("&filter[attribute]=le:value", filterString);
         }
 
         [Fact]
@@ -54,4 +75,4 @@ public void NoFilter_Compose_EmptyStringReturned()
             Assert.Equal("", filterString); 
         }
     }
-}
\ No newline at end of file
+}

From 38f7c191e4eba20725491e5d7e29e4885d638436 Mon Sep 17 00:00:00 2001
From: Faraz Ahmed <Farazuddin.Ahmed@kalibrate.com>
Date: Mon, 7 May 2018 15:20:17 -0400
Subject: [PATCH 149/227] fixes #277


From 1ac47484e4e878d59643ec31b032006aa7b30952 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Mon, 7 May 2018 15:08:18 -0500
Subject: [PATCH 150/227] bump package version

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index ccebe08784..53649bb7e7 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.2.2</VersionPrefix>
+    <VersionPrefix>2.2.3</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From ffaacf68a1e049ee3dc1d12227abaafc83e5e549 Mon Sep 17 00:00:00 2001
From: Faraz Ahmed <Farazuddin.Ahmed@kalibrate.com>
Date: Mon, 7 May 2018 16:12:27 -0400
Subject: [PATCH 151/227] validation fix

---
 src/JsonApiDotNetCore/Services/QueryComposer.cs | 3 ++-
 test/UnitTests/Services/QueryComposerTests.cs   | 4 +++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/QueryComposer.cs b/src/JsonApiDotNetCore/Services/QueryComposer.cs
index 9747f6d47d..8e0819a438 100644
--- a/src/JsonApiDotNetCore/Services/QueryComposer.cs
+++ b/src/JsonApiDotNetCore/Services/QueryComposer.cs
@@ -31,7 +31,8 @@ public string Compose(IJsonApiContext jsonApiContext)
         private string ComposeSingleFilter(FilterQuery query)
         {
             var result = "&filter";
-            result += QueryConstants.OPEN_BRACKET + query.Attribute + QueryConstants.CLOSE_BRACKET + "=" + query.Operation + ":" + query.Value;
+            var operation = string.IsNullOrWhiteSpace(query.Operation) ? query.Operation : query.Operation + ":";
+            result += QueryConstants.OPEN_BRACKET + query.Attribute + QueryConstants.CLOSE_BRACKET + "=" + operation + query.Value;
             return result;
         }
     }
diff --git a/test/UnitTests/Services/QueryComposerTests.cs b/test/UnitTests/Services/QueryComposerTests.cs
index cf54d10a5a..91df486212 100644
--- a/test/UnitTests/Services/QueryComposerTests.cs
+++ b/test/UnitTests/Services/QueryComposerTests.cs
@@ -42,9 +42,11 @@ public void Can_ComposeLessThan_FilterStringForUrl()
         {
             // arrange
             var filter = new FilterQuery("attribute", "value", "le");
+            var filter2 = new FilterQuery("attribute2", "value2", "");
             var querySet = new QuerySet();
             List<FilterQuery> filters = new List<FilterQuery>();
             filters.Add(filter);
+            filters.Add(filter2);
             querySet.Filters = filters;
 
             _jsonApiContext
@@ -55,7 +57,7 @@ public void Can_ComposeLessThan_FilterStringForUrl()
             // act
             var filterString = queryComposer.Compose(_jsonApiContext.Object);
             // assert
-            Assert.Equal("&filter[attribute]=le:value", filterString);
+            Assert.Equal("&filter[attribute]=le:value&filter[attribute2]=value2", filterString);
         }
 
         [Fact]

From 19e976bb03420ed78b4b09e749fa352568772ecb Mon Sep 17 00:00:00 2001
From: Corey Floyd <cfloyd@appriver.com>
Date: Tue, 8 May 2018 08:27:54 -0500
Subject: [PATCH 152/227] #218 Defaults data to be included in relationships
 rather than only when "include" for that relationship is set.

---
 .../Builders/DocumentBuilder.cs               | 25 ++++++++-----------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 0e43225b35..3edea50e13 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -158,20 +158,17 @@ private void AddRelationships(DocumentData data, ContextEntity contextEntity, II
                     if (r.DocumentLinks.HasFlag(Link.Related))
                         relationshipData.Links.Related = linkBuilder.GetRelatedRelationLink(contextEntity.EntityName, entity.StringId, r.PublicRelationshipName);
                 }
-
-                if (RelationshipIsIncluded(r.PublicRelationshipName))
-                {
-                    var navigationEntity = _jsonApiContext.ContextGraph
-                        .GetRelationship(entity, r.InternalRelationshipName);
-
-                    if (navigationEntity == null)
-                        relationshipData.SingleData = null;
-                    else if (navigationEntity is IEnumerable)
-                        relationshipData.ManyData = GetRelationships((IEnumerable<object>)navigationEntity);
-                    else
-                        relationshipData.SingleData = GetRelationship(navigationEntity);
-                }
-
+                
+                var navigationEntity = _jsonApiContext.ContextGraph
+                    .GetRelationship(entity, r.InternalRelationshipName);
+
+                if (navigationEntity == null)
+                    relationshipData.SingleData = null;
+                else if (navigationEntity is IEnumerable)
+                    relationshipData.ManyData = GetRelationships((IEnumerable<object>)navigationEntity);
+                else
+                    relationshipData.SingleData = GetRelationship(navigationEntity);
+                
                 data.Relationships.Add(r.PublicRelationshipName, relationshipData);
             });
         }

From 4ccae8b58b34a6e3fef4a91c2a69e11adea90e0a Mon Sep 17 00:00:00 2001
From: Corey Floyd <cfloyd@appriver.com>
Date: Fri, 11 May 2018 09:53:21 -0500
Subject: [PATCH 153/227] #218 Adds unit test verify relationhip data included
 in resource relationships with id and type set.

---
 .../Builders/DocumentBuilder_Tests.cs         | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index 7946efa058..36d280054c 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -28,6 +28,7 @@ public DocumentBuilder_Tests()
             _options.BuildContextGraph(builder =>
             {
                 builder.AddResource<Model>("models");
+                builder.AddResource<RelatedModel>("related-models");
             });
 
             _jsonApiContextMock
@@ -121,6 +122,37 @@ public void Related_Links_Can_Be_Disabled()
             Assert.Null(document.Data.Relationships["related-model"].Links);
         }
 
+        [Fact]
+        public void Related_Data_Included_In_Relationships_By_Default()
+        {
+            // arrange
+            const string relationshipName = "related-models";
+            const int relatedId = 1;
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model
+            {
+                RelatedModel = new RelatedModel
+                {
+                    Id = relatedId
+                }
+            };
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            var relationshipData = document.Data.Relationships[relationshipName];
+            Assert.NotNull(relationshipData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
+            Assert.Equal(relationshipName, relationshipData.SingleData.Type);
+        }
+
         [Fact]
         public void Build_Can_Build_Arrays()
         {

From 3e46dee7a8cbdd024f20691c2b4a7ad3734a04b3 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 15 May 2018 10:37:19 -0500
Subject: [PATCH 154/227] fix tests by separating relationship and type names

---
 .../Builders/DocumentBuilder_Tests.cs         | 25 ++++++++++---------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index 36d280054c..b2131f6ec9 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -60,7 +60,7 @@ public DocumentBuilder_Tests()
         [Fact]
         public void Includes_Paging_Links_By_Default()
         {
-            // arrange            
+            // arrange
             _pageManager.PageSize = 1;
             _pageManager.TotalRecords = 1;
             _pageManager.CurrentPage = 1;
@@ -126,7 +126,8 @@ public void Related_Links_Can_Be_Disabled()
         public void Related_Data_Included_In_Relationships_By_Default()
         {
             // arrange
-            const string relationshipName = "related-models";
+            const string relatedTypeName = "related-models";
+            const string relationshipName = "related-model";
             const int relatedId = 1;
             _jsonApiContextMock
                 .Setup(m => m.ContextGraph)
@@ -148,9 +149,9 @@ public void Related_Data_Included_In_Relationships_By_Default()
             var relationshipData = document.Data.Relationships[relationshipName];
             Assert.NotNull(relationshipData);
             Assert.NotNull(relationshipData.SingleData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
-            Assert.Equal(relationshipName, relationshipData.SingleData.Type);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
+            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
         }
 
         [Fact]
@@ -177,12 +178,12 @@ public void Build_Can_Build_CustomIEnumerables()
 
 
         [Theory]
-        [InlineData(null,null,true)]
-        [InlineData(false,null,true)]
-        [InlineData(true,null,false)]
-        [InlineData(null,"foo",true)]
-        [InlineData(false,"foo",true)]
-        [InlineData(true,"foo",true)]
+        [InlineData(null, null, true)]
+        [InlineData(false, null, true)]
+        [InlineData(true, null, false)]
+        [InlineData(null, "foo", true)]
+        [InlineData(false, "foo", true)]
+        [InlineData(true, "foo", true)]
         public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
             string attributeValue,
             bool resultContainsAttribute)
@@ -194,7 +195,7 @@ public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
                     .Returns(new DocumentBuilderOptions(omitNullValuedAttributes.Value));
             }
             var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, null, omitNullValuedAttributes.HasValue ? documentBuilderBehaviourMock.Object : null);
-            var document = documentBuilder.Build(new Model(){StringProperty = attributeValue});
+            var document = documentBuilder.Build(new Model() { StringProperty = attributeValue });
 
             Assert.Equal(resultContainsAttribute, document.Data.Attributes.ContainsKey("StringProperty"));
         }

From a5730bfdedfa95b2f8f265c37a9e47fa4ff314f6 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Tue, 15 May 2018 11:24:09 -0500
Subject: [PATCH 155/227] chore(csproj): bump package version

also add build property for docfx targets
closes #283
---
 .../JsonApiDotNetCore.csproj                  | 21 ++++++++-----------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 53649bb7e7..eb649ed5dc 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,9 +1,10 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.2.3</VersionPrefix>
+    <VersionPrefix>2.2.4</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>
+    <LangVersion>7.2</LangVersion>
   </PropertyGroup>
 
   <PropertyGroup>
@@ -25,20 +26,16 @@
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
   </ItemGroup>
 
-  <!-- XML documentation -->
-  <PropertyGroup>
+  <!-- 
+    To generate DocFX documentation on Windows platforms: dotnet build -c Release /p:DocFx=true
+  -->
+  <PropertyGroup Condition="'$(Configuration)' == 'Release'">
     <IsWindows Condition="'$(OS)' == 'Windows_NT'">true</IsWindows>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+    <GenerateDocumentation Condition="'$(IsWindows)|$(DocFx)' == 'true|true'">true</GenerateDocumentation>
     <DocumentationFile>bin\Release\netstandard2.0\JsonApiDotNetCore.xml</DocumentationFile>
   </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
-    <LangVersion>7.2</LangVersion>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
-    <LangVersion>7.2</LangVersion>
-  </PropertyGroup>
-  <ItemGroup Condition="$(IsWindows)=='true'">
+
+  <ItemGroup Condition="'$(GenerateDocumentation)' == 'true'">
     <PackageReference Include="docfx.console" Version="2.33.0" />
   </ItemGroup>
 

From 3c98b70375dbcec7c13a91903eba479b8816b271 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Tue, 15 May 2018 14:09:56 -0500
Subject: [PATCH 156/227] fix(#218): include independent hasOne identifier in
 all requests for the dependent side of the relationship by default

---
 .../Builders/DocumentBuilder.cs               | 85 ++++++++++++-------
 .../Models/HasOneAttribute.cs                 | 54 ++++++++++--
 .../Serialization/JsonApiDeSerializer.cs      |  6 +-
 .../Builders/DocumentBuilder_Tests.cs         | 29 +++++++
 4 files changed, 134 insertions(+), 40 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 3edea50e13..49d40e0f28 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -13,9 +13,9 @@ public class DocumentBuilder : IDocumentBuilder
         private readonly IJsonApiContext _jsonApiContext;
         private readonly IContextGraph _contextGraph;
         private readonly IRequestMeta _requestMeta;
-        private readonly DocumentBuilderOptions _documentBuilderOptions; 
+        private readonly DocumentBuilderOptions _documentBuilderOptions;
 
-        public DocumentBuilder(IJsonApiContext jsonApiContext, IRequestMeta requestMeta=null, IDocumentBuilderOptionsProvider documentBuilderOptionsProvider=null)
+        public DocumentBuilder(IJsonApiContext jsonApiContext, IRequestMeta requestMeta = null, IDocumentBuilderOptionsProvider documentBuilderOptionsProvider = null)
         {
             _jsonApiContext = jsonApiContext;
             _contextGraph = jsonApiContext.ContextGraph;
@@ -143,34 +143,42 @@ private bool OmitNullValuedAttribute(AttrAttribute attr, object attributeValue)
         private void AddRelationships(DocumentData data, ContextEntity contextEntity, IIdentifiable entity)
         {
             data.Relationships = new Dictionary<string, RelationshipData>();
+            contextEntity.Relationships.ForEach(r =>
+                data.Relationships.Add(
+                    r.PublicRelationshipName,
+                    GetRelationshipData(r, contextEntity, entity)
+                )
+            );
+        }
+
+        private RelationshipData GetRelationshipData(RelationshipAttribute attr, ContextEntity contextEntity, IIdentifiable entity)
+        {
             var linkBuilder = new LinkBuilder(_jsonApiContext);
 
-            contextEntity.Relationships.ForEach(r =>
+            var relationshipData = new RelationshipData();
+
+            if (attr.DocumentLinks.HasFlag(Link.None) == false)
             {
-                var relationshipData = new RelationshipData();
+                relationshipData.Links = new Links();
+                if (attr.DocumentLinks.HasFlag(Link.Self))
+                    relationshipData.Links.Self = linkBuilder.GetSelfRelationLink(contextEntity.EntityName, entity.StringId, attr.PublicRelationshipName);
 
-                if (r.DocumentLinks.HasFlag(Link.None) == false)
-                {
-                    relationshipData.Links = new Links();
-                    if (r.DocumentLinks.HasFlag(Link.Self))
-                        relationshipData.Links.Self = linkBuilder.GetSelfRelationLink(contextEntity.EntityName, entity.StringId, r.PublicRelationshipName);
+                if (attr.DocumentLinks.HasFlag(Link.Related))
+                    relationshipData.Links.Related = linkBuilder.GetRelatedRelationLink(contextEntity.EntityName, entity.StringId, attr.PublicRelationshipName);
+            }
 
-                    if (r.DocumentLinks.HasFlag(Link.Related))
-                        relationshipData.Links.Related = linkBuilder.GetRelatedRelationLink(contextEntity.EntityName, entity.StringId, r.PublicRelationshipName);
-                }
-                
-                var navigationEntity = _jsonApiContext.ContextGraph
-                    .GetRelationship(entity, r.InternalRelationshipName);
-
-                if (navigationEntity == null)
-                    relationshipData.SingleData = null;
-                else if (navigationEntity is IEnumerable)
-                    relationshipData.ManyData = GetRelationships((IEnumerable<object>)navigationEntity);
-                else
-                    relationshipData.SingleData = GetRelationship(navigationEntity);
-                
-                data.Relationships.Add(r.PublicRelationshipName, relationshipData);
-            });
+            // this only includes the navigation property, we need to actually check the navigation property Id
+            var navigationEntity = _jsonApiContext.ContextGraph.GetRelationship(entity, attr.InternalRelationshipName);
+            if (navigationEntity == null)
+                relationshipData.SingleData = attr.IsHasOne
+                    ? GetIndependentRelationshipIdentifier((HasOneAttribute)attr, entity)
+                    : null;
+            else if (navigationEntity is IEnumerable)
+                relationshipData.ManyData = GetRelationships((IEnumerable<object>)navigationEntity);
+            else
+                relationshipData.SingleData = GetRelationship(navigationEntity);
+
+            return relationshipData;
         }
 
         private List<DocumentData> GetIncludedEntities(List<DocumentData> included, ContextEntity contextEntity, IIdentifiable entity)
@@ -240,23 +248,40 @@ private List<ResourceIdentifierObject> GetRelationships(IEnumerable<object> enti
             var relationships = new List<ResourceIdentifierObject>();
             foreach (var entity in entities)
             {
-                relationships.Add(new ResourceIdentifierObject {
+                relationships.Add(new ResourceIdentifierObject
+                {
                     Type = typeName.EntityName,
                     Id = ((IIdentifiable)entity).StringId
                 });
             }
             return relationships;
         }
+
         private ResourceIdentifierObject GetRelationship(object entity)
         {
             var objType = entity.GetType();
+            var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(objType);
 
-            var typeName = _jsonApiContext.ContextGraph.GetContextEntity(objType);
-
-            return new ResourceIdentifierObject {
-                Type = typeName.EntityName,
+            return new ResourceIdentifierObject
+            {
+                Type = contextEntity.EntityName,
                 Id = ((IIdentifiable)entity).StringId
             };
         }
+
+        private ResourceIdentifierObject GetIndependentRelationshipIdentifier(HasOneAttribute hasOne, IIdentifiable entity)
+        {
+            var independentRelationshipIdentifier = hasOne.GetIdentifiablePropertyValue(entity);
+            if (independentRelationshipIdentifier == null)
+                return null;
+
+            var relatedContextEntity = _jsonApiContext.ContextGraph.GetContextEntity(hasOne.Type);
+
+            return new ResourceIdentifierObject
+            {
+                Type = relatedContextEntity.EntityName,
+                Id = independentRelationshipIdentifier.ToString()
+            };
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
index f863c8819b..de7b7822f6 100644
--- a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
@@ -2,21 +2,61 @@ namespace JsonApiDotNetCore.Models
 {
     public class HasOneAttribute : RelationshipAttribute
     {
-        public HasOneAttribute(string publicName, Link documentLinks = Link.All, bool canInclude = true)
+        /// <summary>
+        /// Create a HasOne relational link to another entity
+        /// </summary>
+        /// 
+        /// <param name="publicName">The relationship name as exposed by the API</param>
+        /// <param name="documentLinks">Which links are available. Defaults to <see cref="Link.All"/></param>
+        /// <param name="canInclude">Whether or not this relationship can be included using the <c>?include=public-name</c> query string</param>
+        /// <param name="withForiegnKey">The foreign key property name. Defaults to <c>"{RelationshipName}Id"</c></param>
+        /// 
+        /// <example>
+        /// Using an alternative foreign key:
+        /// 
+        /// <code>
+        /// public class Article : Identifiable 
+        /// {
+        ///     [HasOne("author", withForiegnKey: nameof(AuthorKey)]
+        ///     public Author Author { get; set; }
+        ///     public int AuthorKey { get; set; }
+        /// }
+        /// </code>
+        /// 
+        /// </example>
+        public HasOneAttribute(string publicName, Link documentLinks = Link.All, bool canInclude = true, string withForiegnKey = null)
         : base(publicName, documentLinks, canInclude)
-        { }
+        {
+            _explicitIdentifiablePropertyName = withForiegnKey;
+        }
+
+        private readonly string _explicitIdentifiablePropertyName;
+
+        /// <summary>
+        /// The independent entity identifier.
+        /// </summary>
+        public string IdentifiablePropertyName => string.IsNullOrWhiteSpace(_explicitIdentifiablePropertyName)
+            ? $"{InternalRelationshipName}Id"
+            : _explicitIdentifiablePropertyName;
 
         public override void SetValue(object entity, object newValue)
         {
-            var propertyName = (newValue.GetType() == Type) 
-                ? InternalRelationshipName 
-                : $"{InternalRelationshipName}Id";
-                
+            var propertyName = (newValue.GetType() == Type)
+                ? InternalRelationshipName
+                : IdentifiablePropertyName;
+
             var propertyInfo = entity
                 .GetType()
                 .GetProperty(propertyName);
-            
+
             propertyInfo.SetValue(entity, newValue);
         }
+
+        // HACK: this will likely require boxing
+        // we should be able to move some of the reflection into the ContextGraphBuilder
+        internal object GetIdentifiablePropertyValue(object entity) => entity
+                .GetType()
+                .GetProperty(IdentifiablePropertyName)
+                .GetValue(entity);
     }
 }
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 649d6435ff..6fb7af55e1 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -175,7 +175,7 @@ private object SetRelationships(
             foreach (var attr in contextEntity.Relationships)
             {
                 entity = attr.IsHasOne
-                    ? SetHasOneRelationship(entity, entityProperties, attr, contextEntity, relationships)
+                    ? SetHasOneRelationship(entity, entityProperties, (HasOneAttribute)attr, contextEntity, relationships)
                     : SetHasManyRelationship(entity, entityProperties, attr, contextEntity, relationships);
             }
 
@@ -184,7 +184,7 @@ private object SetRelationships(
 
         private object SetHasOneRelationship(object entity,
             PropertyInfo[] entityProperties,
-            RelationshipAttribute attr,
+            HasOneAttribute attr,
             ContextEntity contextEntity,
             Dictionary<string, RelationshipData> relationships)
         {
@@ -204,7 +204,7 @@ private object SetHasOneRelationship(object entity,
 
                 var newValue = rio.Id;
 
-                var foreignKey = attr.InternalRelationshipName + "Id";
+                var foreignKey = attr.IdentifiablePropertyName;
                 var entityProperty = entityProperties.FirstOrDefault(p => p.Name == foreignKey);
                 if (entityProperty == null)
                     throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a foreign key property '{foreignKey}' for has one relationship '{attr.InternalRelationshipName}'");
diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index b2131f6ec9..dbca1bebb4 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -145,6 +145,35 @@ public void Related_Data_Included_In_Relationships_By_Default()
             // act
             var document = documentBuilder.Build(entity);
 
+            // assert
+            var relationshipData = document.Data.Relationships[relationshipName];
+            Assert.NotNull(relationshipData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
+            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
+        }
+
+        [Fact]
+        public void IndependentIdentifier__Included_In_HasOne_Relationships_By_Default()
+        {
+            // arrange
+            const string relatedTypeName = "related-models";
+            const string relationshipName = "related-model";
+            const int relatedId = 1;
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model
+            {
+                RelatedModelId = relatedId
+            };
+
+            // act
+            var document = documentBuilder.Build(entity);
+
             // assert
             var relationshipData = document.Data.Relationships[relationshipName];
             Assert.NotNull(relationshipData);

From f34cca7c9f518f7351394839668effffa10e73c4 Mon Sep 17 00:00:00 2001
From: Milos <Milos@DESKTOP-DK5COF9>
Date: Fri, 25 May 2018 10:44:14 +0200
Subject: [PATCH 157/227] Add Negative filter

---
 src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs | 4 ++++
 src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs | 5 +++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index 73e3a14a3e..79eda6c598 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -195,6 +195,10 @@ private static Expression GetFilterExpressionLambda(Expression left, Expression
                 case FilterOperations.like:
                     body = Expression.Call(left, "Contains", null, right);
                     break;
+                    // {model.Id != 1}
+                case FilterOperations.ne:
+                    body = Expression.NotEqual(left, right);
+                    break;
                 default:
                     throw new JsonApiException(500, $"Unknown filter operation {operation}");
             }
diff --git a/src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs b/src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs
index 260dc32655..e3c207ce47 100644
--- a/src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs
@@ -8,6 +8,7 @@ public enum FilterOperations
         gt = 2,
         le = 3,
         ge = 4,
-        like = 5
+        like = 5,
+        ne = 6
     }
-}
\ No newline at end of file
+}

From 6210cc6355150fc4443062cd47993bd5dcd23870 Mon Sep 17 00:00:00 2001
From: Milos <Milos@DESKTOP-DK5COF9>
Date: Fri, 25 May 2018 17:19:54 +0200
Subject: [PATCH 158/227] Add NotEqual acceptance test

---
 .../Acceptance/Spec/AttributeFilterTests.cs   | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index 083b2c22d7..df68f06eb0 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -105,5 +105,32 @@ public async Task Cannot_Filter_If_Explicitly_Forbidden()
             // assert
             Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
         }
+
+        [Fact]
+        public async Task Can_Filter_On_Not_Equal_Values()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var todoItems = _todoItemFaker.Generate(5); 
+            context.TodoItems.AddRange(todoItems);
+            await context.SaveChangesAsync();
+
+            var lastTodoItem = context.TodoItems.Last();
+            var httpMethod = new HttpMethod("GET");
+            var route = $"/api/v1/todo-items?filter[guid-property]=ne:{lastTodoItem.GuidProperty}";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // act
+            var response = await _fixture.Client.SendAsync(request);
+            var body = await response.Content.ReadAsStringAsync();
+            var deserializedTodoItems = _fixture
+                .GetService<IJsonApiDeSerializer>()
+                .DeserializeList<TodoItem>(body);
+
+            // assert
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Equal(deserializedTodoItems.Count(), todoItems.Count() -1);
+            Assert.False(deserializedTodoItems.Any(i => i.GuidProperty == lastTodoItem.GuidProperty));
+        }
     }
 }

From 4126f36265d94a5eadd3ece10a3caa8526e1562b Mon Sep 17 00:00:00 2001
From: Milos <Milos@DESKTOP-DK5COF9>
Date: Fri, 25 May 2018 17:55:19 +0200
Subject: [PATCH 159/227] Changed Count

---
 .../Acceptance/Spec/AttributeFilterTests.cs                     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index df68f06eb0..e1d92be3b6 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -129,7 +129,7 @@ public async Task Can_Filter_On_Not_Equal_Values()
 
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-            Assert.Equal(deserializedTodoItems.Count(), todoItems.Count() -1);
+            Assert.Equal(deserializedTodoItems.Count, todoItems.Count() -1);
             Assert.False(deserializedTodoItems.Any(i => i.GuidProperty == lastTodoItem.GuidProperty));
         }
     }

From 91a5699d469278da3f1072a236e062135db1abb1 Mon Sep 17 00:00:00 2001
From: Milos <Milos@DESKTOP-UMA0C8Q>
Date: Sat, 26 May 2018 23:58:46 +0200
Subject: [PATCH 160/227] Fix NotEqual filter test

---
 .../Acceptance/Spec/AttributeFilterTests.cs           | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index e1d92be3b6..b84b57e31b 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -111,13 +111,13 @@ public async Task Can_Filter_On_Not_Equal_Values()
         {
             // arrange
             var context = _fixture.GetService<AppDbContext>();
-            var todoItems = _todoItemFaker.Generate(5); 
-            context.TodoItems.AddRange(todoItems);
+            var todoItem = _todoItemFaker.Generate();
+            context.TodoItems.Add(todoItem);
             await context.SaveChangesAsync();
 
-            var lastTodoItem = context.TodoItems.Last();
+            var totalCount = context.TodoItems.Count();
             var httpMethod = new HttpMethod("GET");
-            var route = $"/api/v1/todo-items?filter[guid-property]=ne:{lastTodoItem.GuidProperty}";
+            var route = $"/api/v1/todo-items?page[size]={totalCount}&filter[ordinal]=ne:{todoItem.Ordinal}";
             var request = new HttpRequestMessage(httpMethod, route);
 
             // act
@@ -129,8 +129,7 @@ public async Task Can_Filter_On_Not_Equal_Values()
 
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-            Assert.Equal(deserializedTodoItems.Count, todoItems.Count() -1);
-            Assert.False(deserializedTodoItems.Any(i => i.GuidProperty == lastTodoItem.GuidProperty));
+            Assert.False(deserializedTodoItems.Any(i => i.Ordinal == todoItem.Ordinal));
         }
     }
 }

From 7ad0eb8040dea726401a42efa16a6ab82ea54756 Mon Sep 17 00:00:00 2001
From: Milos <Milos@DESKTOP-UMA0C8Q>
Date: Tue, 29 May 2018 12:25:41 +0200
Subject: [PATCH 161/227] Add IN filter for array searching

---
 .../Extensions/IQueryableExtensions.cs        | 107 +++++++++++++-----
 .../Internal/Query/FilterOperations.cs        |   3 +-
 src/JsonApiDotNetCore/Internal/TypeHelper.cs  |  24 ++++
 src/JsonApiDotNetCore/Services/QueryParser.cs |  47 +++++---
 .../Acceptance/Spec/AttributeFilterTests.cs   |  71 ++++++++++++
 5 files changed, 208 insertions(+), 44 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index 79eda6c598..c392da2b93 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
+using System.Reflection;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Services;
@@ -101,21 +102,30 @@ public static IQueryable<TSource> Filter<TSource>(this IQueryable<TSource> sourc
 
             try
             {
-                // convert the incoming value to the target value type
-                // "1" -> 1
-                var convertedValue = TypeHelper.ConvertType(filterQuery.PropertyValue, property.PropertyType);
-                // {model}
-                var parameter = Expression.Parameter(concreteType, "model");
-                // {model.Id}
-                var left = Expression.PropertyOrField(parameter, property.Name);
-                // {1}
-                var right = Expression.Constant(convertedValue, property.PropertyType);
-
-                var body = GetFilterExpressionLambda(left, right, filterQuery.FilterOperation);
-
-                var lambda = Expression.Lambda<Func<TSource, bool>>(body, parameter);
-
-                return source.Where(lambda);
+                if (filterQuery.FilterOperation == FilterOperations.@in )
+                {
+                    string[] propertyValues = filterQuery.PropertyValue.Split(',');
+                    var lambdaIn = ArrayContainsPredicate<TSource>(propertyValues, property.Name);
+
+                    return source.Where(lambdaIn);
+                }
+                else
+                {   // convert the incoming value to the target value type
+                    // "1" -> 1
+                    var convertedValue = TypeHelper.ConvertType(filterQuery.PropertyValue, property.PropertyType);
+                    // {model}
+                    var parameter = Expression.Parameter(concreteType, "model");
+                    // {model.Id}
+                    var left = Expression.PropertyOrField(parameter, property.Name);
+                    // {1}
+                    var right = Expression.Constant(convertedValue, property.PropertyType);
+
+                    var body = GetFilterExpressionLambda(left, right, filterQuery.FilterOperation);
+
+                    var lambda = Expression.Lambda<Func<TSource, bool>>(body, parameter);
+
+                    return source.Where(lambda);
+                }
             }
             catch (FormatException)
             {
@@ -140,26 +150,36 @@ public static IQueryable<TSource> Filter<TSource>(this IQueryable<TSource> sourc
 
             try
             {
-                // convert the incoming value to the target value type
-                // "1" -> 1
-                var convertedValue = TypeHelper.ConvertType(filterQuery.PropertyValue, relatedAttr.PropertyType);
-                // {model}
-                var parameter = Expression.Parameter(concreteType, "model");
+                if (filterQuery.FilterOperation == FilterOperations.@in)
+                {
+                    string[] propertyValues = filterQuery.PropertyValue.Split(',');
+                    var lambdaIn = ArrayContainsPredicate<TSource>(propertyValues, relatedAttr.Name, relation.Name);
+
+                    return source.Where(lambdaIn);
+                }
+                else
+                {
+                    // convert the incoming value to the target value type
+                    // "1" -> 1
+                    var convertedValue = TypeHelper.ConvertType(filterQuery.PropertyValue, relatedAttr.PropertyType);
+                    // {model}
+                    var parameter = Expression.Parameter(concreteType, "model");
 
-                // {model.Relationship}
-                var leftRelationship = Expression.PropertyOrField(parameter, relation.Name);
+                    // {model.Relationship}
+                    var leftRelationship = Expression.PropertyOrField(parameter, relation.Name);
 
-                // {model.Relationship.Attr}
-                var left = Expression.PropertyOrField(leftRelationship, relatedAttr.Name);
+                    // {model.Relationship.Attr}
+                    var left = Expression.PropertyOrField(leftRelationship, relatedAttr.Name);
 
-                // {1}
-                var right = Expression.Constant(convertedValue, relatedAttr.PropertyType);
+                    // {1}
+                    var right = Expression.Constant(convertedValue, relatedAttr.PropertyType);
 
-                var body = GetFilterExpressionLambda(left, right, filterQuery.FilterOperation);
+                    var body = GetFilterExpressionLambda(left, right, filterQuery.FilterOperation);
 
-                var lambda = Expression.Lambda<Func<TSource, bool>>(body, parameter);
+                    var lambda = Expression.Lambda<Func<TSource, bool>>(body, parameter);
 
-                return source.Where(lambda);
+                    return source.Where(lambda);
+                }
             }
             catch (FormatException)
             {
@@ -206,6 +226,35 @@ private static Expression GetFilterExpressionLambda(Expression left, Expression
             return body;
         }
 
+        private static Expression<Func<TSource, bool>> ArrayContainsPredicate<TSource>(string[] propertyValues, string fieldname, string relationName = null)
+        {
+            ParameterExpression entity = Expression.Parameter(typeof(TSource), "entity");
+            MemberExpression member;
+            if (!string.IsNullOrEmpty(relationName))
+            {
+                var relation = Expression.PropertyOrField(entity, relationName);
+                member = Expression.Property(relation, fieldname);
+            }
+            else
+                member = Expression.Property(entity, fieldname);
+
+            var containsMethods = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(m => m.Name == "Contains");
+            MethodInfo method = null;
+            foreach (var m in containsMethods)
+            {
+                if (m.GetParameters().Count() == 2)
+                {
+                    method = m;
+                    break;
+                }
+            }
+            method = method.MakeGenericMethod(member.Type);
+            var obj = TypeHelper.ConvertListType(propertyValues, member.Type);
+
+            var exprContains = Expression.Call(method, new Expression[] { Expression.Constant(obj), member });
+            return Expression.Lambda<Func<TSource, bool>>(exprContains, entity);
+        }
+
         public static IQueryable<TSource> Select<TSource>(this IQueryable<TSource> source, List<string> columns)
         {
             if (columns == null || columns.Count == 0)
diff --git a/src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs b/src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs
index e3c207ce47..88a2da2ee8 100644
--- a/src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/FilterOperations.cs
@@ -9,6 +9,7 @@ public enum FilterOperations
         le = 3,
         ge = 4,
         like = 5,
-        ne = 6
+        ne = 6,
+        @in = 7, // prefix with @ to use keyword
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/TypeHelper.cs b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
index cc64b398dd..15bd322e54 100644
--- a/src/JsonApiDotNetCore/Internal/TypeHelper.cs
+++ b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
@@ -1,4 +1,6 @@
 using System;
+using System.Collections;
+using System.Collections.Generic;
 using System.Reflection;
 
 namespace JsonApiDotNetCore.Internal
@@ -54,5 +56,27 @@ public static T ConvertType<T>(object value)
         {
             return (T)ConvertType(value, typeof(T));
         }
+
+        /// <summary>
+        /// Convert collection of query string params to Collection of concrete Type
+        /// </summary>
+        /// <param name="values">Collection like ["10","20","30"]</param>
+        /// <param name="type">Non array type. For e.g. int</param>
+        /// <returns>Collection of concrete type</returns>
+        public static object ConvertListType(IEnumerable<string> values, Type type)
+        {
+            var convertedArray = new List<object>();
+            foreach (var value in values)
+            {
+                convertedArray.Add(ConvertType(value, type));
+            }
+            var listType = typeof(List<>).MakeGenericType(type);
+            IList list = (IList)Activator.CreateInstance(listType);
+            foreach (var item in convertedArray)
+            {
+                list.Add(item);
+            }
+            return list;
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index b1a1c26f31..239ee8a3b8 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -82,14 +82,23 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
             // expected input = filter[id]=1
             // expected input = filter[id]=eq:1
             var queries = new List<FilterQuery>();
-
             var propertyName = key.Split(QueryConstants.OPEN_BRACKET, QueryConstants.CLOSE_BRACKET)[1];
 
-            var values = value.Split(QueryConstants.COMMA);
-            foreach (var val in values)
+            // InArray case
+            var op = GetFilterOperation(value);
+            if (op == FilterOperations.@in.ToString())
+            {
+                (var operation, var filterValue) = ParseFilterOperation(value);
+                queries.Add(new FilterQuery(propertyName, filterValue, op));
+            }
+            else
             {
-                (var operation, var filterValue) = ParseFilterOperation(val);
-                queries.Add(new FilterQuery(propertyName, filterValue, operation));
+                var values = value.Split(QueryConstants.COMMA);
+                foreach (var val in values)
+                {
+                    (var operation, var filterValue) = ParseFilterOperation(val);
+                    queries.Add(new FilterQuery(propertyName, filterValue, operation));
+                }
             }
 
             return queries;
@@ -100,19 +109,15 @@ protected virtual (string operation, string value) ParseFilterOperation(string v
             if (value.Length < 3)
                 return (string.Empty, value);
 
-            var operation = value.Split(QueryConstants.COLON);
+            var operation = GetFilterOperation(value);
+            var values = value.Split(QueryConstants.COLON);
 
-            if (operation.Length == 1)
-                return (string.Empty, value);
-
-            // remove prefix from value
-            if (Enum.TryParse(operation[0], out FilterOperations op) == false)
+            if (string.IsNullOrEmpty(operation))
                 return (string.Empty, value);
 
-            var prefix = operation[0];
-            value = string.Join(QueryConstants.COLON_STR, operation.Skip(1));
+            value = string.Join(QueryConstants.COLON_STR, values.Skip(1));
 
-            return (prefix, value);
+            return (operation, value);
         }
 
         protected virtual PageQuery ParsePageQuery(PageQuery pageQuery, string key, string value)
@@ -225,6 +230,20 @@ protected virtual AttrAttribute GetAttribute(string propertyName)
             }
         }
 
+        private string GetFilterOperation(string value)
+        {
+            var operation = value.Split(QueryConstants.COLON);
+
+            if (operation.Length == 1)
+                return string.Empty;
+
+            // remove prefix from value
+            if (Enum.TryParse(operation[0], out FilterOperations op) == false)
+                return string.Empty;
+
+            return operation[0];
+        }
+
         private FilterQuery BuildFilterQuery(ReadOnlySpan<char> query, string propertyName)
         {
             var (operation, filterValue) = ParseFilterOperation(query.ToString());
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index b84b57e31b..b8927f71a8 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
@@ -8,6 +9,7 @@
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
+using Microsoft.EntityFrameworkCore;
 using Newtonsoft.Json;
 using Xunit;
 using Person = JsonApiDotNetCoreExample.Models.Person;
@@ -131,5 +133,74 @@ public async Task Can_Filter_On_Not_Equal_Values()
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.False(deserializedTodoItems.Any(i => i.Ordinal == todoItem.Ordinal));
         }
+
+        [Fact]
+        public async Task Can_Filter_On_In_Array_Values()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var todoItems = _todoItemFaker.Generate(3);
+            var guids = new List<Guid>();
+            foreach (var item in todoItems)
+            {
+                context.TodoItems.Add(item);
+                guids.Add(item.GuidProperty);
+            }
+            context.SaveChanges();
+
+            var totalCount = context.TodoItems.Count();
+            var httpMethod = new HttpMethod("GET");
+            var route = $"/api/v1/todo-items?filter[guid-property]=in:{string.Join(",", guids)}";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // act
+            var response = await _fixture.Client.SendAsync(request);
+            var body = await response.Content.ReadAsStringAsync();
+            var deserializedTodoItems = _fixture
+                .GetService<IJsonApiDeSerializer>()
+                .DeserializeList<TodoItem>(body);
+
+            // assert
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Equal(guids.Count(), deserializedTodoItems.Count());
+            foreach (var item in deserializedTodoItems)
+                Assert.True(guids.Contains(item.GuidProperty));
+        }
+
+        [Fact]
+        public async Task Can_Filter_On_Related_In_Array_Values()
+        {
+            // arrange
+            var context = _fixture.GetService<AppDbContext>();
+            var todoItems = _todoItemFaker.Generate(3);
+            var ownerFirstNames = new List<string>();
+            foreach (var item in todoItems)
+            {
+                var person = _personFaker.Generate();
+                ownerFirstNames.Add(person.FirstName);
+                item.Owner = person;
+                context.TodoItems.Add(item);               
+            }
+            context.SaveChanges();
+
+            var httpMethod = new HttpMethod("GET");
+            var route = $"/api/v1/todo-items?include=owner&filter[owner.first-name]=in:{string.Join(",", ownerFirstNames)}";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // act
+            var response = await _fixture.Client.SendAsync(request);
+            var body = await response.Content.ReadAsStringAsync();
+            var documents = JsonConvert.DeserializeObject<Documents>(await response.Content.ReadAsStringAsync());
+            var included = documents.Included;
+
+            // assert
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Equal(ownerFirstNames.Count(), documents.Data.Count());
+            Assert.NotNull(included);
+            Assert.NotEmpty(included);
+            foreach (var item in included)
+                Assert.True(ownerFirstNames.Contains(item.Attributes["first-name"]));
+
+        }
     }
 }

From 912f45c6b31a55864cd3bba7ab592250102dbe79 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 5 Jun 2018 05:45:57 -0500
Subject: [PATCH 162/227] fix(HasOneAttribute): return null if property doesnt
 exist

---
 src/JsonApiDotNetCore/Models/HasOneAttribute.cs | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
index de7b7822f6..03fdb200fc 100644
--- a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
@@ -54,9 +54,20 @@ public override void SetValue(object entity, object newValue)
 
         // HACK: this will likely require boxing
         // we should be able to move some of the reflection into the ContextGraphBuilder
+        /// <summary>
+        /// Gets the value of the independent identifier (e.g. Article.AuthorId)
+        /// </summary>
+        /// 
+        /// <param name="entity">
+        /// An instance of dependent resource
+        /// </param>
+        /// 
+        /// <returns>
+        /// The property value or null if the property does not exist on the model.
+        /// </returns>
         internal object GetIdentifiablePropertyValue(object entity) => entity
                 .GetType()
                 .GetProperty(IdentifiablePropertyName)
-                .GetValue(entity);
+                ?.GetValue(entity);
     }
 }

From 40c8ffe77940b1e0063c7e78d08c9cda6289ae5b Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 5 Jun 2018 06:11:02 -0500
Subject: [PATCH 163/227] fix(DocumentBuilder): handle case when hasOne
 relationship type is unknown

---
 src/JsonApiDotNetCore/Builders/DocumentBuilder.cs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 49d40e0f28..088a2bf092 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -276,6 +276,8 @@ private ResourceIdentifierObject GetIndependentRelationshipIdentifier(HasOneAttr
                 return null;
 
             var relatedContextEntity = _jsonApiContext.ContextGraph.GetContextEntity(hasOne.Type);
+            if (relatedContextEntity == null) // TODO: this should probably be a debug log at minimum
+                return null;
 
             return new ResourceIdentifierObject
             {

From 65bb454108bca0d9f28629977ce23ce5fe587f71 Mon Sep 17 00:00:00 2001
From: Milos <Milos@DESKTOP-DK5COF9>
Date: Wed, 6 Jun 2018 10:16:03 +0200
Subject: [PATCH 164/227] Code improvements of "in" filtering

---
 .../Extensions/IQueryableExtensions.cs        | 29 ++++++++++++-------
 src/JsonApiDotNetCore/Internal/TypeHelper.cs  | 12 +++-----
 src/JsonApiDotNetCore/Services/QueryParser.cs | 13 +++++----
 .../Acceptance/Spec/AttributeFilterTests.cs   | 12 ++++++--
 4 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
index c392da2b93..994fc08070 100644
--- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs
@@ -12,6 +12,23 @@ namespace JsonApiDotNetCore.Extensions
     // ReSharper disable once InconsistentNaming
     public static class IQueryableExtensions
     {
+        private static MethodInfo _containsMethod;
+        private static MethodInfo ContainsMethod
+        {
+            get
+            {
+                if (_containsMethod == null)
+                {
+                    _containsMethod = typeof(Enumerable)
+                      .GetMethods(BindingFlags.Static | BindingFlags.Public)
+                      .Where(m => m.Name == nameof(Enumerable.Contains) && m.GetParameters().Count() == 2)
+                      .First();
+                }
+                return _containsMethod;
+            }
+        }
+
+
         public static IQueryable<TSource> Sort<TSource>(this IQueryable<TSource> source, List<SortQuery> sortQueries)
         {
             if (sortQueries == null || sortQueries.Count == 0)
@@ -238,17 +255,7 @@ private static Expression<Func<TSource, bool>> ArrayContainsPredicate<TSource>(s
             else
                 member = Expression.Property(entity, fieldname);
 
-            var containsMethods = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(m => m.Name == "Contains");
-            MethodInfo method = null;
-            foreach (var m in containsMethods)
-            {
-                if (m.GetParameters().Count() == 2)
-                {
-                    method = m;
-                    break;
-                }
-            }
-            method = method.MakeGenericMethod(member.Type);
+            var method = ContainsMethod.MakeGenericMethod(member.Type);
             var obj = TypeHelper.ConvertListType(propertyValues, member.Type);
 
             var exprContains = Expression.Call(method, new Expression[] { Expression.Constant(obj), member });
diff --git a/src/JsonApiDotNetCore/Internal/TypeHelper.cs b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
index 15bd322e54..5135473cdb 100644
--- a/src/JsonApiDotNetCore/Internal/TypeHelper.cs
+++ b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
@@ -63,19 +63,15 @@ public static T ConvertType<T>(object value)
         /// <param name="values">Collection like ["10","20","30"]</param>
         /// <param name="type">Non array type. For e.g. int</param>
         /// <returns>Collection of concrete type</returns>
-        public static object ConvertListType(IEnumerable<string> values, Type type)
+        public static IList ConvertListType(IEnumerable<string> values, Type type)
         {
-            var convertedArray = new List<object>();
-            foreach (var value in values)
-            {
-                convertedArray.Add(ConvertType(value, type));
-            }
             var listType = typeof(List<>).MakeGenericType(type);
             IList list = (IList)Activator.CreateInstance(listType);
-            foreach (var item in convertedArray)
+            foreach (var value in values)
             {
-                list.Add(item);
+                list.Add(ConvertType(value, type));
             }
+
             return list;
         }
     }
diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs
index 239ee8a3b8..7e17352815 100644
--- a/src/JsonApiDotNetCore/Services/QueryParser.cs
+++ b/src/JsonApiDotNetCore/Services/QueryParser.cs
@@ -85,8 +85,8 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
             var propertyName = key.Split(QueryConstants.OPEN_BRACKET, QueryConstants.CLOSE_BRACKET)[1];
 
             // InArray case
-            var op = GetFilterOperation(value);
-            if (op == FilterOperations.@in.ToString())
+            string op = GetFilterOperation(value);
+            if (string.Equals(op, FilterOperations.@in.ToString(), StringComparison.OrdinalIgnoreCase))
             {
                 (var operation, var filterValue) = ParseFilterOperation(value);
                 queries.Add(new FilterQuery(propertyName, filterValue, op));
@@ -232,16 +232,17 @@ protected virtual AttrAttribute GetAttribute(string propertyName)
 
         private string GetFilterOperation(string value)
         {
-            var operation = value.Split(QueryConstants.COLON);
+            var values = value.Split(QueryConstants.COLON);
 
-            if (operation.Length == 1)
+            if (values.Length == 1)
                 return string.Empty;
 
+            var operation = values[0];
             // remove prefix from value
-            if (Enum.TryParse(operation[0], out FilterOperations op) == false)
+            if (Enum.TryParse(operation, out FilterOperations op) == false)
                 return string.Empty;
 
-            return operation[0];
+            return operation;
         }
 
         private FilterQuery BuildFilterQuery(ReadOnlySpan<char> query, string propertyName)
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index b8927f71a8..428e3cadf3 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -139,12 +139,17 @@ public async Task Can_Filter_On_In_Array_Values()
         {
             // arrange
             var context = _fixture.GetService<AppDbContext>();
-            var todoItems = _todoItemFaker.Generate(3);
+            var todoItems = _todoItemFaker.Generate(5);
             var guids = new List<Guid>();
+            var notInGuids = new List<Guid>();
             foreach (var item in todoItems)
             {
                 context.TodoItems.Add(item);
-                guids.Add(item.GuidProperty);
+                // Exclude 2 items
+                if (guids.Count < (todoItems.Count() - 2))
+                    guids.Add(item.GuidProperty);
+                else 
+                    notInGuids.Add(item.GuidProperty);
             }
             context.SaveChanges();
 
@@ -164,7 +169,10 @@ public async Task Can_Filter_On_In_Array_Values()
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.Equal(guids.Count(), deserializedTodoItems.Count());
             foreach (var item in deserializedTodoItems)
+            {
                 Assert.True(guids.Contains(item.GuidProperty));
+                Assert.False(notInGuids.Contains(item.GuidProperty));
+            }
         }
 
         [Fact]

From a9342e2b1219c1f087b362931f0c87705ac5511f Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 7 Apr 2018 18:33:55 -0500
Subject: [PATCH 165/227] fix(Deserializer): remove dependency on
 GenericProcessorFactory

Rather than fetching data from the database during deserialization, we can set the relationships with instances that just carry the id. It will then be the responsibility of the repository to handle those relationships
---
 .../Extensions/TypeExtensions.cs              | 23 ++++++++++
 .../Serialization/JsonApiDeSerializer.cs      | 29 ++++++++----
 .../Extensions/TypeExtensions_Tests.cs        | 44 +++++++++++++++++++
 3 files changed, 88 insertions(+), 8 deletions(-)
 create mode 100644 test/UnitTests/Extensions/TypeExtensions_Tests.cs

diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
index ccc4619966..a78f545e81 100644
--- a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -31,5 +31,28 @@ public static Type GetElementType(this IEnumerable enumerable)
 
             return elementType;
         }
+
+        /// <summary>
+        /// Creates a List{TInterface} where TInterface is the generic for type specified by t
+        /// </summary>
+        public static List<TInterface> GetEmptyCollection<TInterface>(this Type t)
+        {
+            if (t == null) throw new ArgumentNullException(nameof(t));
+
+            var listType = typeof(List<>).MakeGenericType(t);
+            var list = (List<TInterface>)Activator.CreateInstance(listType);
+            return list;
+        }
+
+        /// <summary>
+        /// Creates a new instance of type t, casting it to the specified TInterface 
+        /// </summary>
+        public static TInterface New<TInterface>(this Type t)
+        {
+            if (t == null) throw new ArgumentNullException(nameof(t));
+
+            var instance = (TInterface)Activator.CreateInstance(t);
+            return instance;
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 6fb7af55e1..d55cb48a2e 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -9,20 +9,27 @@
 using JsonApiDotNetCore.Services;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
+using JsonApiDotNetCore.Extensions;
 
 namespace JsonApiDotNetCore.Serialization
 {
     public class JsonApiDeSerializer : IJsonApiDeSerializer
     {
         private readonly IJsonApiContext _jsonApiContext;
-        private readonly IGenericProcessorFactory _genericProcessorFactory;
 
+        [Obsolete(
+            "The deserializer no longer depends on the IGenericProcessorFactory",
+            error: false)]
         public JsonApiDeSerializer(
             IJsonApiContext jsonApiContext,
             IGenericProcessorFactory genericProcessorFactory)
         {
             _jsonApiContext = jsonApiContext;
-            _genericProcessorFactory = genericProcessorFactory;
+        }
+
+        public JsonApiDeSerializer(IJsonApiContext jsonApiContext)
+        {
+            _jsonApiContext = jsonApiContext;
         }
 
         public object Deserialize(string requestBody)
@@ -225,10 +232,11 @@ private object SetHasManyRelationship(object entity,
             ContextEntity contextEntity,
             Dictionary<string, RelationshipData> relationships)
         {
-            var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
+            // TODO: is this necessary? if not, remove
+            // var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
 
-            if (entityProperty == null)
-                throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain an relationsip named {attr.InternalRelationshipName}");
+            // if (entityProperty == null)
+            //     throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a relationsip named '{attr.InternalRelationshipName}'");
 
             var relationshipName = attr.PublicRelationshipName;
 
@@ -238,11 +246,16 @@ private object SetHasManyRelationship(object entity,
 
                 if (data == null) return entity;
 
-                var genericProcessor = _genericProcessorFactory.GetProcessor<IGenericProcessor>(typeof(GenericProcessor<>), attr.Type);
+                var resourceRelationships = attr.Type.GetEmptyCollection<IIdentifiable>();
 
-                var ids = relationshipData.ManyData.Select(r => r.Id);
+                var relationshipShells = relationshipData.ManyData.Select(r =>
+                {
+                    var instance = attr.Type.New<IIdentifiable>();
+                    instance.StringId = r.Id;
+                    return instance;
+                });
 
-                genericProcessor.SetRelationships(entity, attr, ids);
+                attr.SetValue(entity, relationshipShells);
             }
 
             return entity;
diff --git a/test/UnitTests/Extensions/TypeExtensions_Tests.cs b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
new file mode 100644
index 0000000000..92534eef5d
--- /dev/null
+++ b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
@@ -0,0 +1,44 @@
+using JsonApiDotNetCore.Models;
+using Xunit;
+using JsonApiDotNetCore.Extensions;
+using System.Collections.Generic;
+
+namespace UnitTests.Extensions
+{
+    public class TypeExtensions_Tests
+    {
+        [Fact]
+        public void GetCollection_Creates_List_If_T_Implements_Interface()
+        {
+            // arrange
+            var type = typeof(Model);
+
+            // act
+            var collection = type.GetEmptyCollection<IIdentifiable>();
+
+            // assert
+            Assert.NotNull(collection);
+            Assert.Empty(collection);
+            Assert.IsType<List<Model>>(collection);
+        }
+
+        [Fact]
+        public void New_Creates_An_Instance_If_T_Implements_Interface()
+        {
+            // arrange
+            var type = typeof(Model);
+
+            // act
+            var instance = type.New<IIdentifiable>();
+
+            // assert
+            Assert.NotNull(instance);
+            Assert.IsType<Model>(instance);
+        }
+
+        private class Model : IIdentifiable
+        {
+            public string StringId { get; set; }
+        }
+    }
+}

From a0b284dfbc369a91df561cd89216a2fa9921da94 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 7 Apr 2018 19:08:18 -0500
Subject: [PATCH 166/227] fix(typeExtensions): cast to IEnumerable using
 covariance

---
 src/JsonApiDotNetCore/Extensions/TypeExtensions.cs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
index a78f545e81..efe29620f8 100644
--- a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -35,12 +35,12 @@ public static Type GetElementType(this IEnumerable enumerable)
         /// <summary>
         /// Creates a List{TInterface} where TInterface is the generic for type specified by t
         /// </summary>
-        public static List<TInterface> GetEmptyCollection<TInterface>(this Type t)
+        public static IEnumerable<TInterface> GetEmptyCollection<TInterface>(this Type t)
         {
             if (t == null) throw new ArgumentNullException(nameof(t));
 
             var listType = typeof(List<>).MakeGenericType(t);
-            var list = (List<TInterface>)Activator.CreateInstance(listType);
+            var list = (IEnumerable<TInterface>)Activator.CreateInstance(listType);
             return list;
         }
 

From 1e134cf53a63b4c195873a82833b21a738c1430b Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sat, 7 Apr 2018 20:57:26 -0500
Subject: [PATCH 167/227] fix(Deserializer): properly convert collection type
 when setting it on the model

---
 src/JsonApiDotNetCore/Extensions/TypeExtensions.cs     |  4 ++--
 src/JsonApiDotNetCore/Internal/TypeHelper.cs           |  8 ++++++++
 src/JsonApiDotNetCore/Models/HasManyAttribute.cs       |  2 +-
 .../Serialization/JsonApiDeSerializer.cs               | 10 ++++++----
 test/UnitTests/Extensions/TypeExtensions_Tests.cs      |  6 +++---
 5 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
index efe29620f8..8cc7c0dffe 100644
--- a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -35,12 +35,12 @@ public static Type GetElementType(this IEnumerable enumerable)
         /// <summary>
         /// Creates a List{TInterface} where TInterface is the generic for type specified by t
         /// </summary>
-        public static IEnumerable<TInterface> GetEmptyCollection<TInterface>(this Type t)
+        public static IEnumerable GetEmptyCollection(this Type t)
         {
             if (t == null) throw new ArgumentNullException(nameof(t));
 
             var listType = typeof(List<>).MakeGenericType(t);
-            var list = (IEnumerable<TInterface>)Activator.CreateInstance(listType);
+            var list = (IEnumerable)Activator.CreateInstance(listType);
             return list;
         }
 
diff --git a/src/JsonApiDotNetCore/Internal/TypeHelper.cs b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
index 5135473cdb..0a3e01d0d1 100644
--- a/src/JsonApiDotNetCore/Internal/TypeHelper.cs
+++ b/src/JsonApiDotNetCore/Internal/TypeHelper.cs
@@ -7,6 +7,14 @@ namespace JsonApiDotNetCore.Internal
 {
     public static class TypeHelper
     {
+        public static IList ConvertCollection(IEnumerable<object> collection, Type targetType)
+        {
+            var list = Activator.CreateInstance(typeof(List<>).MakeGenericType(targetType)) as IList;
+            foreach(var item in collection)
+                list.Add(ConvertType(item, targetType));
+            return list;
+        }
+
         public static object ConvertType(object value, Type type)
         {
             if (value == null)
diff --git a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
index 4519dc8cb6..c2d7594400 100644
--- a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
@@ -12,7 +12,7 @@ public override void SetValue(object entity, object newValue)
                 .GetType()
                 .GetProperty(InternalRelationshipName);
             
-            propertyInfo.SetValue(entity, newValue);        
+            propertyInfo.SetValue(entity, newValue);
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index d55cb48a2e..723e831e1e 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models;
@@ -9,7 +10,6 @@
 using JsonApiDotNetCore.Services;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
-using JsonApiDotNetCore.Extensions;
 
 namespace JsonApiDotNetCore.Serialization
 {
@@ -246,8 +246,6 @@ private object SetHasManyRelationship(object entity,
 
                 if (data == null) return entity;
 
-                var resourceRelationships = attr.Type.GetEmptyCollection<IIdentifiable>();
-
                 var relationshipShells = relationshipData.ManyData.Select(r =>
                 {
                     var instance = attr.Type.New<IIdentifiable>();
@@ -255,7 +253,11 @@ private object SetHasManyRelationship(object entity,
                     return instance;
                 });
 
-                attr.SetValue(entity, relationshipShells);
+                var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
+
+                // var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
+
+                attr.SetValue(entity, convertedCollection);
             }
 
             return entity;
diff --git a/test/UnitTests/Extensions/TypeExtensions_Tests.cs b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
index 92534eef5d..f59fa37be0 100644
--- a/test/UnitTests/Extensions/TypeExtensions_Tests.cs
+++ b/test/UnitTests/Extensions/TypeExtensions_Tests.cs
@@ -1,7 +1,7 @@
+using System.Collections.Generic;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Models;
 using Xunit;
-using JsonApiDotNetCore.Extensions;
-using System.Collections.Generic;
 
 namespace UnitTests.Extensions
 {
@@ -14,7 +14,7 @@ public void GetCollection_Creates_List_If_T_Implements_Interface()
             var type = typeof(Model);
 
             // act
-            var collection = type.GetEmptyCollection<IIdentifiable>();
+            var collection = type.GetEmptyCollection();
 
             // assert
             Assert.NotNull(collection);

From bc621fada955ba1c6096d593b837edcd133e97c3 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 8 Apr 2018 07:10:26 -0500
Subject: [PATCH 168/227] set new HasManyRelationships with
 EntityState.Unchanged

---
 .../Data/DefaultEntityRepository.cs           | 19 +++++++
 .../Data/IEntityRepository.cs                 |  4 --
 .../Extensions/DbContextExtensions.cs         | 16 ++----
 .../Request/HasManyRelationshipPointers.cs    | 49 +++++++++++++++++++
 .../Serialization/JsonApiDeSerializer.cs      | 10 +---
 .../Services/IJsonApiContext.cs               |  2 +
 .../Services/JsonApiContext.cs                |  2 +
 7 files changed, 78 insertions(+), 24 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index b6bcda29b3..fe85c84049 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -85,10 +85,29 @@ public virtual async Task<TEntity> GetAndIncludeAsync(TId id, string relationshi
         public virtual async Task<TEntity> CreateAsync(TEntity entity)
         {
             _dbSet.Add(entity);
+
+            DetachHasManyPointers();
+
             await _context.SaveChangesAsync();
             return entity;
         }
 
+        /// <summary>
+        /// This is used to allow creation of HasMany relationships when the
+        /// dependent side of the relationship already exists.
+        /// </summary>
+        private void DetachHasManyPointers()
+        {
+            var relationships = _jsonApiContext.HasManyRelationshipPointers.Get();
+            foreach(var relationship in relationships)
+            {
+                foreach(var pointer in relationship.Value)
+                {
+                    _context.Entry(pointer).State = EntityState.Unchanged;
+                }
+            }
+        }
+
         public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
         {
             var oldEntity = await GetAsync(id);
diff --git a/src/JsonApiDotNetCore/Data/IEntityRepository.cs b/src/JsonApiDotNetCore/Data/IEntityRepository.cs
index 4c35d6ea3f..e8bb68ef90 100644
--- a/src/JsonApiDotNetCore/Data/IEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/IEntityRepository.cs
@@ -1,7 +1,3 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
 
 namespace JsonApiDotNetCore.Data
diff --git a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
index 2606342e29..3cb5ccc359 100644
--- a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
@@ -1,20 +1,12 @@
-using Microsoft.EntityFrameworkCore;
 using System;
+using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Extensions
 {
     public static class DbContextExtensions
     {
-        public static DbSet<T> GetDbSet<T>(this DbContext context) where T : class
-        {
-            var contextProperties = context.GetType().GetProperties();
-            foreach(var property in contextProperties)
-            {
-                if (property.PropertyType == typeof(DbSet<T>))
-                    return (DbSet<T>)property.GetValue(context);
-            }
-
-            throw new ArgumentException($"DbSet of type {typeof(T).FullName} not found on the DbContext", nameof(T));
-        }
+        [Obsolete("This is no longer required since the introduction of context.Set<T>", error: false)]
+        public static DbSet<T> GetDbSet<T>(this DbContext context) where T : class 
+            => context.Set<T>();
     }
 }
diff --git a/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs b/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
new file mode 100644
index 0000000000..721274e3d6
--- /dev/null
+++ b/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace JsonApiDotNetCore.Request
+{
+    /// <summary>
+    /// Stores information to set relationships for the request resource. 
+    /// These relationships must already exist and should not be re-created.
+    /// 
+    /// The expected use case is POST-ing or PATCH-ing 
+    /// an entity with HasMany relaitonships:
+    /// <code>
+    /// {
+    ///    "data": {
+    ///      "type": "photos",
+    ///      "attributes": {
+    ///        "title": "Ember Hamster",
+    ///        "src": "http://example.com/images/productivity.png"
+    ///      },
+    ///      "relationships": {
+    ///        "tags": {
+    ///          "data": [
+    ///            { "type": "tags", "id": "2" },
+    ///            { "type": "tags", "id": "3" }
+    ///          ]
+    ///        }
+    ///      }
+    ///    }
+    ///  }
+    /// </code>
+    /// </summary>
+    public class HasManyRelationshipPointers
+    {
+        private Dictionary<Type, IList> _hasManyRelationships = new Dictionary<Type, IList>();
+
+        /// <summary>
+        /// Add the relationship to the list of relationships that should be 
+        /// set in the repository layer.
+        /// </summary>
+        public void Add(Type dependentType, IList entities)
+            => _hasManyRelationships[dependentType] = entities;
+
+        /// <summary>
+        /// Get all the models that should be associated
+        /// </summary>
+        public Dictionary<Type, IList> Get() => _hasManyRelationships;
+    }
+}
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 723e831e1e..5ef13609d6 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -232,12 +232,6 @@ private object SetHasManyRelationship(object entity,
             ContextEntity contextEntity,
             Dictionary<string, RelationshipData> relationships)
         {
-            // TODO: is this necessary? if not, remove
-            // var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalRelationshipName);
-
-            // if (entityProperty == null)
-            //     throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a relationsip named '{attr.InternalRelationshipName}'");
-
             var relationshipName = attr.PublicRelationshipName;
 
             if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
@@ -255,9 +249,9 @@ private object SetHasManyRelationship(object entity,
 
                 var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
 
-                // var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
-
                 attr.SetValue(entity, convertedCollection);
+
+                _jsonApiContext.HasManyRelationshipPointers.Add(attr.Type, convertedCollection);
             }
 
             return entity;
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index a73f0eb53a..132630446d 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -6,6 +6,7 @@
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Request;
 
 namespace JsonApiDotNetCore.Services
 {
@@ -28,6 +29,7 @@ public interface IJsonApiContext
         Type ControllerType { get; set; }
         Dictionary<string, object> DocumentMeta { get; set; }
         bool IsBulkOperationRequest { get; set; }
+        HasManyRelationshipPointers HasManyRelationshipPointers { get; }
 
         TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
     }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 2665217fef..0643d494d6 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -6,6 +6,7 @@
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Request;
 using Microsoft.AspNetCore.Http;
 
 namespace JsonApiDotNetCore.Services
@@ -51,6 +52,7 @@ public JsonApiContext(
         public Type ControllerType { get; set; }
         public Dictionary<string, object> DocumentMeta { get; set; }
         public bool IsBulkOperationRequest { get; set; }
+        public HasManyRelationshipPointers HasManyRelationshipPointers { get; } = new HasManyRelationshipPointers();
 
         public IJsonApiContext ApplyContext<T>(object controller)
         {

From 9ee5a97c11788c763bc262bfff3e5b669d8e58b6 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 8 Apr 2018 07:26:15 -0500
Subject: [PATCH 169/227] ensure pointers are attached prior to adding the
 entity

---
 src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index fe85c84049..032fef13c4 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -84,10 +84,9 @@ public virtual async Task<TEntity> GetAndIncludeAsync(TId id, string relationshi
 
         public virtual async Task<TEntity> CreateAsync(TEntity entity)
         {
+            AttachHasManyPointers();
             _dbSet.Add(entity);
 
-            DetachHasManyPointers();
-
             await _context.SaveChangesAsync();
             return entity;
         }
@@ -96,7 +95,7 @@ public virtual async Task<TEntity> CreateAsync(TEntity entity)
         /// This is used to allow creation of HasMany relationships when the
         /// dependent side of the relationship already exists.
         /// </summary>
-        private void DetachHasManyPointers()
+        private void AttachHasManyPointers()
         {
             var relationships = _jsonApiContext.HasManyRelationshipPointers.Get();
             foreach(var relationship in relationships)

From 5fbf2e8a660ee6a3371e22fe69a61a0968a47bbc Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 8 Apr 2018 15:33:58 -0500
Subject: [PATCH 170/227] fix tests

---
 .../Unit => UnitTests}/Builders/MetaBuilderTests.cs        | 6 +++---
 .../Extensions/IServiceCollectionExtensionsTests.cs        | 7 +++----
 .../Unit => UnitTests}/Models/AttributesEqualsTests.cs     | 2 +-
 test/UnitTests/UnitTests.csproj                            | 1 +
 4 files changed, 8 insertions(+), 8 deletions(-)
 rename test/{JsonApiDotNetCoreExampleTests/Unit => UnitTests}/Builders/MetaBuilderTests.cs (97%)
 rename test/{JsonApiDotNetCoreExampleTests/Unit => UnitTests}/Extensions/IServiceCollectionExtensionsTests.cs (92%)
 rename test/{JsonApiDotNetCoreExampleTests/Unit => UnitTests}/Models/AttributesEqualsTests.cs (97%)

diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs b/test/UnitTests/Builders/MetaBuilderTests.cs
similarity index 97%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs
rename to test/UnitTests/Builders/MetaBuilderTests.cs
index 5cd0b765de..0b784ef5b7 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Builders/MetaBuilderTests.cs
+++ b/test/UnitTests/Builders/MetaBuilderTests.cs
@@ -1,8 +1,8 @@
-using Xunit;
-using JsonApiDotNetCore.Builders;
 using System.Collections.Generic;
+using JsonApiDotNetCore.Builders;
+using Xunit;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Builders
+namespace UnitTests.Builders
 {
     public class MetaBuilderTests
     {
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
similarity index 92%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
rename to test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
index f6772fa22b..4fe2f09ff1 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs
+++ b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
@@ -10,12 +10,11 @@
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Caching.Memory;
 using Microsoft.Extensions.DependencyInjection;
-using UnitTests;
 using Xunit;
+using Microsoft.EntityFrameworkCore;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Extensions
+namespace UnitTests.Extensions
 {
     public class IServiceCollectionExtensionsTests
     {
@@ -28,7 +27,7 @@ public void AddJsonApiInternals_Adds_All_Required_Services()
 
             services.AddDbContext<AppDbContext>(options =>
             {
-                options.UseMemoryCache(new MemoryCache(new MemoryCacheOptions()));
+                options.UseInMemoryDatabase();
             }, ServiceLifetime.Transient);
 
             // act
diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs b/test/UnitTests/Models/AttributesEqualsTests.cs
similarity index 97%
rename from test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs
rename to test/UnitTests/Models/AttributesEqualsTests.cs
index 107dd1d593..0b989169ef 100644
--- a/test/JsonApiDotNetCoreExampleTests/Unit/Models/AttributesEqualsTests.cs
+++ b/test/UnitTests/Models/AttributesEqualsTests.cs
@@ -1,7 +1,7 @@
 using JsonApiDotNetCore.Models;
 using Xunit;
 
-namespace JsonApiDotNetCoreExampleTests.Unit.Models
+namespace UnitTests.Models
 {
     public class AttributesEqualsTests
     {
diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj
index 14a0d30e33..a6ed346e7d 100644
--- a/test/UnitTests/UnitTests.csproj
+++ b/test/UnitTests/UnitTests.csproj
@@ -12,5 +12,6 @@
     <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
     <PackageReference Include="xunit" Version="$(XUnitVersion)" />
     <PackageReference Include="Moq" Version="$(MoqVersion)" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.2" />
   </ItemGroup>
 </Project>

From 46df3b50ad127bdcc330bde5b04b633c03377e4e Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 10 May 2018 14:18:38 -0500
Subject: [PATCH 171/227] add serialization tests

---
 .../Serialization/JsonApiDeSerializerTests.cs | 261 +++++++++++-------
 1 file changed, 163 insertions(+), 98 deletions(-)

diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index 1e20c0359e..0b80d3a25a 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -2,8 +2,8 @@
 using System.Collections.Generic;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Request;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
 using Moq;
@@ -11,10 +11,13 @@
 using Newtonsoft.Json.Serialization;
 using Xunit;
 
-namespace UnitTests.Serialization {
-    public class JsonApiDeSerializerTests {
+namespace UnitTests.Serialization
+{
+    public class JsonApiDeSerializerTests
+    {
         [Fact]
-        public void Can_Deserialize_Complex_Types() {
+        public void Can_Deserialize_Complex_Types()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -29,20 +32,18 @@ public void Can_Deserialize_Complex_Types() {
             jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
-
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "test-resource",
-                Id = "1",
-                Attributes = new Dictionary<string, object> {
+            var content = new Document
+            {
+                Data = new DocumentData
                 {
-                "complex-member",
-                new { compoundName = "testName" }
-                }
-                }
+                    Type = "test-resource",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object>
+                    {
+                        { "complex-member", new { compoundName = "testName" } }
+                    }
                 }
             };
 
@@ -55,7 +56,8 @@ public void Can_Deserialize_Complex_Types() {
         }
 
         [Fact]
-        public void Can_Deserialize_Complex_List_Types() {
+        public void Can_Deserialize_Complex_List_Types()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResourceWithList>("test-resource");
@@ -69,22 +71,18 @@ public void Can_Deserialize_Complex_List_Types() {
             jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
-
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "test-resource",
-                Id = "1",
-                Attributes = new Dictionary<string, object> {
+            var content = new Document
+            {
+                Data = new DocumentData
                 {
-                "complex-members",
-                new [] {
-                new { compoundName = "testName" }
-                }
-                }
-                }
+                    Type = "test-resource",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object>
+                    {
+                        { "complex-members", new [] { new { compoundName = "testName" } } }
+                    }
                 }
             };
 
@@ -98,7 +96,8 @@ public void Can_Deserialize_Complex_List_Types() {
         }
 
         [Fact]
-        public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs() {
+        public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -113,20 +112,20 @@ public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs() {
             jsonApiOptions.SerializerSettings.ContractResolver = new DasherizedResolver(); // <--
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
-
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "test-resource",
-                Id = "1",
-                Attributes = new Dictionary<string, object> {
+            var content = new Document
+            {
+                Data = new DocumentData
                 {
-                "complex-member",
-                new Dictionary<string, string> { { "compound-name", "testName" } }
-                }
-                }
+                    Type = "test-resource",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object>
+                    {
+                        {
+                            "complex-member", new Dictionary<string, string> { { "compound-name", "testName" } }
+                        }
+                    }
                 }
             };
 
@@ -139,7 +138,8 @@ public void Can_Deserialize_Complex_Types_With_Dasherized_Attrs() {
         }
 
         [Fact]
-        public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate() {
+        public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<TestResource>("test-resource");
@@ -156,22 +156,21 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate() {
             jsonApiOptions.SerializerSettings.ContractResolver = new DasherizedResolver();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
-
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "test-resource",
-                Id = "1",
-                Attributes = new Dictionary<string, object> {
+            var content = new Document
+            {
+                Data = new DocumentData
                 {
-                "complex-member",
-                new Dictionary<string, string> { { "compound-name", "testName" }
-                }
-                },
-                { "immutable", "value" }
-                }
+                    Type = "test-resource",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object>
+                    {
+                        {
+                            "complex-member", new Dictionary<string, string> { { "compound-name", "testName" } }
+                        },
+                        { "immutable", "value" }
+                    }
                 }
             };
 
@@ -189,7 +188,8 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate() {
         }
 
         [Fact]
-        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship() {
+        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<Independent>("independents");
@@ -204,17 +204,16 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship() {
             var jsonApiOptions = new JsonApiOptions();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
-
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
             var property = Guid.NewGuid().ToString();
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "independents",
-                Id = "1",
-                Attributes = new Dictionary<string, object> { { "property", property }
-                }
+            var content = new Document
+            {
+                Data = new DocumentData
+                {
+                    Type = "independents",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object> { { "property", property } }
                 }
             };
 
@@ -229,7 +228,8 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship() {
         }
 
         [Fact]
-        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Relationship_Body() {
+        public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Relationship_Body()
+        {
             // arrange
             var contextGraphBuilder = new ContextGraphBuilder();
             contextGraphBuilder.AddResource<Independent>("independents");
@@ -244,20 +244,18 @@ public void Can_Deserialize_Independent_Side_Of_One_To_One_Relationship_With_Rel
             var jsonApiOptions = new JsonApiOptions();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
-
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
             var property = Guid.NewGuid().ToString();
-            var content = new Document {
-                Data = new DocumentData {
-                Type = "independents",
-                Id = "1",
-                Attributes = new Dictionary<string, object> { { "property", property }
-                },
-                // a common case for this is deserialization in unit tests
-                Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } }
-                }
+            var content = new Document
+            {
+                Data = new DocumentData
+                {
+                    Type = "independents",
+                    Id = "1",
+                    Attributes = new Dictionary<string, object> { { "property", property } },
+                    // a common case for this is deserialization in unit tests
+                    Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } } }
                 }
             };
 
@@ -288,24 +286,21 @@ public void Sets_The_DocumentMeta_Property_In_JsonApiContext()
             var jsonApiOptions = new JsonApiOptions();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
 
-            var genericProcessorFactoryMock = new Mock<IGenericProcessorFactory>();
 
-            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object, genericProcessorFactoryMock.Object);
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
 
             var property = Guid.NewGuid().ToString();
-            
+
             var content = new Document
-            {   
-                Meta = new Dictionary<string, object>() { {"foo", "bar"}},
+            {
+                Meta = new Dictionary<string, object>() { { "foo", "bar" } },
                 Data = new DocumentData
                 {
                     Type = "independents",
                     Id = "1",
-                    Attributes = new Dictionary<string, object> { { "property", property }
-                    },
+                    Attributes = new Dictionary<string, object> { { "property", property } },
                     // a common case for this is deserialization in unit tests
-                    Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } }
-                    }
+                    Relationships = new Dictionary<string, RelationshipData> { { "dependent", new RelationshipData { } } }
                 }
             };
 
@@ -318,32 +313,102 @@ public void Sets_The_DocumentMeta_Property_In_JsonApiContext()
             jsonApiContextMock.VerifySet(mock => mock.DocumentMeta = content.Meta);
         }
 
-
-        private class TestResource : Identifiable {
+        private class TestResource : Identifiable
+        {
             [Attr("complex-member")]
             public ComplexType ComplexMember { get; set; }
 
-            [Attr("immutable", isImmutable : true)]
+            [Attr("immutable", isImmutable: true)]
             public string Immutable { get; set; }
         }
 
-        private class TestResourceWithList : Identifiable {
+        private class TestResourceWithList : Identifiable
+        {
             [Attr("complex-members")]
             public List<ComplexType> ComplexMembers { get; set; }
         }
 
-        private class ComplexType {
+        private class ComplexType
+        {
             public string CompoundName { get; set; }
         }
 
-        private class Independent : Identifiable {
+        private class Independent : Identifiable
+        {
             [Attr("property")] public string Property { get; set; }
             [HasOne("dependent")] public Dependent Dependent { get; set; }
         }
 
-        private class Dependent : Identifiable {
+        private class Dependent : Identifiable
+        {
             [HasOne("independent")] public Independent Independent { get; set; }
             public int IndependentId { get; set; }
         }
+
+
+
+        [Fact]
+        public void Can_Deserialize_Object_With_HasManyRelationship()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<OneToManyIndependent>("independents");
+            contextGraphBuilder.AddResource<OneToManyDependent>("dependents");
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+            jsonApiContextMock.Setup(m => m.HasManyRelationshipPointers).Returns(new HasManyRelationshipPointers());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
+
+            var contentString =
+            @"{
+                ""data"": {
+                    ""type"": ""independents"",
+                    ""id"": ""1"",
+                    ""attributes"": { },
+                    ""relationships"": {
+                        ""dependents"": {
+                            ""data"": [
+                                {
+                                    ""type"": ""dependents"",
+                                    ""id"": ""2""
+                                }
+                            ]
+                        }
+                    }
+                }
+            }";
+
+            // act
+            var result = deserializer.Deserialize<OneToManyIndependent>(contentString);
+
+            // assert
+            Assert.NotNull(result);
+            Assert.Equal(1, result.Id);
+            Assert.NotNull(result.Dependents);
+            Assert.NotEmpty(result.Dependents);
+            Assert.Equal(1, result.Dependents.Count);
+
+            var dependent = result.Dependents[0];
+            Assert.Equal(2, dependent.Id);
+        }
+
+        private class OneToManyDependent : Identifiable
+        {
+            [HasOne("independent")] public OneToManyIndependent Independent { get; set; }
+            public int IndependentId { get; set; }
+        }
+
+        private class OneToManyIndependent : Identifiable
+        {
+            [HasMany("dependents")] public List<OneToManyDependent> Dependents { get; set; }
+        }
     }
 }

From 846e3fc479e54fca01ebeab2635e0ac7d8370e52 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 10 May 2018 17:00:12 -0500
Subject: [PATCH 172/227] refactor(JsonApiContext): begin interface separation

remove redundant IsRelationship property
---
 .../Builders/DocumentBuilder.cs               |   2 +-
 .../Services/EntityResourceService.cs         |   5 +-
 .../Services/IJsonApiContext.cs               | 108 ++++++++++++++++--
 3 files changed, 99 insertions(+), 16 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 088a2bf092..0beb0516c1 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -107,7 +107,7 @@ public DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
                 Id = entity.StringId
             };
 
-            if (_jsonApiContext.IsRelationshipData)
+            if (_jsonApiContext.IsRelationshipPath)
                 return data;
 
             data.Attributes = new Dictionary<string, object>();
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index bc7a2adb52..ba9d6b987e 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -80,10 +80,7 @@ private async Task<T> GetWithRelationshipsAsync(TId id)
         }
 
         public virtual async Task<object> GetRelationshipsAsync(TId id, string relationshipName)
-        {
-            _jsonApiContext.IsRelationshipData = true;
-            return await GetRelationshipAsync(id, relationshipName);
-        }
+            => await GetRelationshipAsync(id, relationshipName);
 
         public virtual async Task<object> GetRelationshipAsync(TId id, string relationshipName)
         {
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index 132630446d..6a358f4732 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -10,27 +10,113 @@
 
 namespace JsonApiDotNetCore.Services
 {
-    public interface IJsonApiContext
+    public interface IJsonApiApplication
     {
         JsonApiOptions Options { get; set; }
-        IJsonApiContext ApplyContext<T>(object controller);
         IContextGraph ContextGraph { get; set; }
-        ContextEntity RequestEntity { get; set; }
-        string BasePath { get; set; }
-        QuerySet QuerySet { get; set; }
-        bool IsRelationshipData { get; set; }
+    }
+
+    public interface IQueryRequest
+    {
         List<string> IncludedRelationships { get; set; }
-        bool IsRelationshipPath { get; }
+        QuerySet QuerySet { get; set; }
         PageManager PageManager { get; set; }
-        IMetaBuilder MetaBuilder { get; set; }
-        IGenericProcessorFactory GenericProcessorFactory { get; set; }
+    }
+
+    public interface IUpdateRequest
+    {
         Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; }
         Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
+    }
+
+    public interface IJsonApiRequest : IJsonApiApplication, IUpdateRequest, IQueryRequest
+    {
+        /// <summary>
+        /// The request namespace. This may be an absolute or relative path
+        /// depending upon the configuration.
+        /// </summary>
+        /// <example>
+        /// Absolute: https://example.com/api/v1
+        /// 
+        /// Relative: /api/v1
+        /// </example>
+        string BasePath { get; set; }
+
+        /// <summary>
+        /// Stores information to set relationships for the request resource. 
+        /// These relationships must already exist and should not be re-created.
+        /// By default, it is the responsibility of the repository to use the 
+        /// relationship pointers to persist the relationship.
+        /// 
+        /// The expected use case is POST-ing or PATCH-ing an entity with HasMany 
+        /// relaitonships:
+        /// <code>
+        /// {
+        ///    "data": {
+        ///      "type": "photos",
+        ///      "attributes": {
+        ///        "title": "Ember Hamster",
+        ///        "src": "http://example.com/images/productivity.png"
+        ///      },
+        ///      "relationships": {
+        ///        "tags": {
+        ///          "data": [
+        ///            { "type": "tags", "id": "2" },
+        ///            { "type": "tags", "id": "3" }
+        ///          ]
+        ///        }
+        ///      }
+        ///    }
+        ///  }
+        /// </code>
+        /// </summary>
+        HasManyRelationshipPointers HasManyRelationshipPointers { get; }
+
+        /// <summary>
+        /// If the request is a bulk json:api v1.1 operations request.
+        /// This is determined by the `
+        /// <see cref="JsonApiDotNetCore.Serialization.JsonApiDeSerializer" />` class.
+        /// 
+        /// See [json-api/1254](https://github.com/json-api/json-api/pull/1254) for details.
+        /// </summary>
+        bool IsBulkOperationRequest { get; set; }
+
+        /// <summary>
+        /// The `<see cref="ContextEntity" />`for the target route.
+        /// </summary>
+        /// 
+        /// <example>
+        /// For a `GET /articles` request, `RequestEntity` will be set
+        /// to the `Article` resource representation on the `JsonApiContext`.
+        /// </example>
+        ContextEntity RequestEntity { get; set; }
+
+        /// <summary>
+        /// The concrete type of the controller that was activated by the MVC routing middleware
+        /// </summary>
         Type ControllerType { get; set; }
+
+        /// <summary>
+        /// The json:api meta data at the document level
+        /// </summary>
         Dictionary<string, object> DocumentMeta { get; set; }
-        bool IsBulkOperationRequest { get; set; }
-        HasManyRelationshipPointers HasManyRelationshipPointers { get; }
 
+        /// <summary>
+        /// If the request is on the `{id}/relationships/{relationshipName}` route
+        /// </summary>
+        bool IsRelationshipPath { get; }
+
+        [Obsolete("Use `IsRelationshipPath` instead.")]
+        bool IsRelationshipData { get; set; }
+    }
+
+    public interface IJsonApiContext : IJsonApiRequest
+    {
+        IJsonApiContext ApplyContext<T>(object controller);
+        IMetaBuilder MetaBuilder { get; set; }
+        IGenericProcessorFactory GenericProcessorFactory { get; set; }
+
+        [Obsolete("Use the proxied method IControllerContext.GetControllerAttribute instead.")]
         TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
     }
 }

From 48c6b5a586a96cfca80994e538976ebfcf75819a Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 5 Jun 2018 07:01:18 -0500
Subject: [PATCH 173/227] document(IUpdateRequest)

---
 src/JsonApiDotNetCore/Services/IJsonApiContext.cs | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index 6a358f4732..52036f21af 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -25,7 +25,16 @@ public interface IQueryRequest
 
     public interface IUpdateRequest
     {
+        /// <summary>
+        /// The attributes that were included in a PATCH request. 
+        /// Only the attributes in this dictionary should be updated.
+        /// </summary>
         Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; }
+
+        /// <summary>
+        /// Any relationships that were included in a PATCH request. 
+        /// Only the relationships in this dictionary should be updated.
+        /// </summary>
         Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
     }
 

From 4ac550e296da13537ba33d9f6d865a6d58670d2b Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 8 Jun 2018 23:01:42 -0500
Subject: [PATCH 174/227] fix(JsonApiDeserializer): if hasOne is nullable allow
 it to be set null

---
 .../Models/HasOneAttribute.cs                 |   7 +-
 .../Models/RelationshipAttribute.cs           |  22 +
 .../Serialization/JsonApiDeSerializer.cs      |  10 +-
 .../Services/EntityResourceService.cs         |   2 +-
 .../Spec/UpdatingRelationshipsTests.cs        |  95 ++++
 .../Builders/DocumentBuilder_Tests.cs         | 529 +++++++++---------
 .../IServiceCollectionExtensionsTests.cs      |   5 +-
 7 files changed, 395 insertions(+), 275 deletions(-)

diff --git a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
index 03fdb200fc..77422027a7 100644
--- a/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasOneAttribute.cs
@@ -39,9 +39,14 @@ public HasOneAttribute(string publicName, Link documentLinks = Link.All, bool ca
             ? $"{InternalRelationshipName}Id"
             : _explicitIdentifiablePropertyName;
 
+        /// <summary>
+        /// Sets the value of the property identified by this attribute
+        /// </summary>
+        /// <param name="entity">The target object</param>
+        /// <param name="newValue">The new property value</param>
         public override void SetValue(object entity, object newValue)
         {
-            var propertyName = (newValue.GetType() == Type)
+            var propertyName = (newValue?.GetType() == Type)
                 ? InternalRelationshipName
                 : IdentifiablePropertyName;
 
diff --git a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
index 2781ecfb53..3e66bdc8aa 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
@@ -19,6 +19,28 @@ protected RelationshipAttribute(string publicName, Link documentLinks, bool canI
         public Link DocumentLinks { get; } = Link.All;
         public bool CanInclude { get; }
 
+        public bool TryGetHasOne(out HasOneAttribute result)
+        {
+            if (IsHasOne)
+            {
+                result = (HasOneAttribute)this;
+                return true;
+            }
+            result = null;
+            return false;
+        }
+
+        public bool TryGetHasMany(out HasManyAttribute result)
+        {
+            if (IsHasMany)
+            {
+                result = (HasManyAttribute)this;
+                return true;
+            }
+            result = null;
+            return false;
+        }
+
         public abstract void SetValue(object entity, object newValue);
 
         public override string ToString()
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 5ef13609d6..da206e4930 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -207,15 +207,17 @@ private object SetHasOneRelationship(object entity,
 
                 var rio = (ResourceIdentifierObject)relationshipData.ExposedData;
 
-                if (rio == null) return entity;
-
-                var newValue = rio.Id;
-
                 var foreignKey = attr.IdentifiablePropertyName;
                 var entityProperty = entityProperties.FirstOrDefault(p => p.Name == foreignKey);
                 if (entityProperty == null)
                     throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a foreign key property '{foreignKey}' for has one relationship '{attr.InternalRelationshipName}'");
 
+                // e.g. PATCH /articles
+                // {... { "relationships":{ "Owner": { "data" :null } } } }
+                if (rio == null && Nullable.GetUnderlyingType(entityProperty.PropertyType) == null)
+                    throw new JsonApiException(400, $"Cannot set required relationship identifier '{attr.IdentifiablePropertyName}' to null.");
+
+                var newValue = rio?.Id ?? null;
                 var convertedValue = TypeHelper.ConvertType(newValue, entityProperty.PropertyType);
 
                 _jsonApiContext.RelationshipsToUpdate[relationshipAttr] = convertedValue;
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index ba9d6b987e..642ee00a57 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -133,7 +133,7 @@ public virtual async Task UpdateRelationshipsAsync(TId id, string relationshipNa
                 .Relationships
                 .FirstOrDefault(r => r.InternalRelationshipName == relationshipName);
 
-            var relationshipIds = relationships.Select(r => r.Id?.ToString());
+            var relationshipIds = relationships.Select(r => r?.Id?.ToString());
 
             await _entities.UpdateRelationshipsAsync(entity, relationship, relationshipIds);
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
index 1dffa6ce87..067483a1b3 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs
@@ -127,5 +127,100 @@ public async Task Can_Update_ToOne_Relationship_ThroughLink()
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotNull(todoItemsOwner);
         }
+
+        [Fact]
+        public async Task Can_Delete_Relationship_By_Patching_Resource()
+        {
+            // arrange
+            var person = _personFaker.Generate();
+            var todoItem = _todoItemFaker.Generate();
+            todoItem.Owner = person;
+
+            _context.People.Add(person);
+            _context.TodoItems.Add(todoItem);
+            _context.SaveChanges();
+
+            var builder = new WebHostBuilder()
+                .UseStartup<Startup>();
+
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+
+            var content = new
+            {
+                data = new
+                {
+                    type = "todo-items",
+                    relationships = new
+                    {
+                        owner = new
+                        {
+                            data = (object)null
+                        }
+                    }
+                }
+            };
+
+            var httpMethod = new HttpMethod("PATCH");
+            var route = $"/api/v1/todo-items/{todoItem.Id}";
+            var request = new HttpRequestMessage(httpMethod, route);
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await client.SendAsync(request);
+
+            // Assert
+            var todoItemResult = _context.TodoItems
+                .AsNoTracking()
+                .Include(t => t.Owner)
+                .Single(t => t.Id == todoItem.Id);
+
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Null(todoItemResult.Owner);
+        }
+
+        [Fact]
+        public async Task Can_Delete_Relationship_By_Patching_Relationship()
+        {
+            // arrange
+            var person = _personFaker.Generate();
+            var todoItem = _todoItemFaker.Generate();
+            todoItem.Owner = person;
+
+            _context.People.Add(person);
+            _context.TodoItems.Add(todoItem);
+            _context.SaveChanges();
+
+            var builder = new WebHostBuilder()
+                .UseStartup<Startup>();
+
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+
+            var content = new
+            {
+                data = (object)null
+            };
+
+            var httpMethod = new HttpMethod("PATCH");
+            var route = $"/api/v1/todo-items/{todoItem.Id}/relationships/owner";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await client.SendAsync(request);
+
+            // Assert
+            var todoItemResult = _context.TodoItems
+                .AsNoTracking()
+                .Include(t => t.Owner)
+                .Single(t => t.Id == todoItem.Id);
+
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Null(todoItemResult.Owner);
+        }
     }
 }
diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index dbca1bebb4..fc816765eb 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -1,268 +1,267 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using JsonApiDotNetCore.Builders;
-using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Models;
-using JsonApiDotNetCore.Services;
-using Moq;
-using Xunit;
-
-namespace UnitTests
-{
-    public class DocumentBuilder_Tests
-    {
-        private readonly Mock<IJsonApiContext> _jsonApiContextMock;
-        private readonly PageManager _pageManager;
-        private readonly JsonApiOptions _options;
-        private readonly Mock<IRequestMeta> _requestMetaMock;
-
-        public DocumentBuilder_Tests()
-        {
-            _jsonApiContextMock = new Mock<IJsonApiContext>();
-            _requestMetaMock = new Mock<IRequestMeta>();
-
-            _options = new JsonApiOptions();
-
-            _options.BuildContextGraph(builder =>
-            {
-                builder.AddResource<Model>("models");
-                builder.AddResource<RelatedModel>("related-models");
-            });
-
-            _jsonApiContextMock
-                .Setup(m => m.Options)
-                .Returns(_options);
-
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            _jsonApiContextMock
-                .Setup(m => m.MetaBuilder)
-                .Returns(new MetaBuilder());
-
-            _pageManager = new PageManager();
-            _jsonApiContextMock
-                .Setup(m => m.PageManager)
-                .Returns(_pageManager);
-
-            _jsonApiContextMock
-                .Setup(m => m.BasePath)
-                .Returns("localhost");
-
-            _jsonApiContextMock
-                .Setup(m => m.RequestEntity)
-                .Returns(_options.ContextGraph.GetContextEntity(typeof(Model)));
-        }
-
-        [Fact]
-        public void Includes_Paging_Links_By_Default()
-        {
-            // arrange
-            _pageManager.PageSize = 1;
-            _pageManager.TotalRecords = 1;
-            _pageManager.CurrentPage = 1;
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model();
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            Assert.NotNull(document.Links);
-            Assert.NotNull(document.Links.Last);
-        }
-
-        [Fact]
-        public void Page_Links_Can_Be_Disabled_Globally()
-        {
-            // arrange
-            _pageManager.PageSize = 1;
-            _pageManager.TotalRecords = 1;
-            _pageManager.CurrentPage = 1;
-
-            _options.BuildContextGraph(builder => builder.DocumentLinks = Link.None);
-
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model();
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            Assert.Null(document.Links);
-        }
-
-        [Fact]
-        public void Related_Links_Can_Be_Disabled()
-        {
-            // arrange
-            _pageManager.PageSize = 1;
-            _pageManager.TotalRecords = 1;
-            _pageManager.CurrentPage = 1;
-
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model();
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            Assert.Null(document.Data.Relationships["related-model"].Links);
-        }
-
-        [Fact]
-        public void Related_Data_Included_In_Relationships_By_Default()
-        {
-            // arrange
-            const string relatedTypeName = "related-models";
-            const string relationshipName = "related-model";
-            const int relatedId = 1;
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model
-            {
-                RelatedModel = new RelatedModel
-                {
-                    Id = relatedId
-                }
-            };
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            var relationshipData = document.Data.Relationships[relationshipName];
-            Assert.NotNull(relationshipData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
-            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
+using System.Collections;
+using System.Collections.Generic;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Services;
+using Moq;
+using Xunit;
+
+namespace UnitTests
+{
+    public class DocumentBuilder_Tests
+    {
+        private readonly Mock<IJsonApiContext> _jsonApiContextMock;
+        private readonly PageManager _pageManager;
+        private readonly JsonApiOptions _options;
+        private readonly Mock<IRequestMeta> _requestMetaMock;
+
+        public DocumentBuilder_Tests()
+        {
+            _jsonApiContextMock = new Mock<IJsonApiContext>();
+            _requestMetaMock = new Mock<IRequestMeta>();
+
+            _options = new JsonApiOptions();
+
+            _options.BuildContextGraph(builder =>
+            {
+                builder.AddResource<Model>("models");
+                builder.AddResource<RelatedModel>("related-models");
+            });
+
+            _jsonApiContextMock
+                .Setup(m => m.Options)
+                .Returns(_options);
+
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            _jsonApiContextMock
+                .Setup(m => m.MetaBuilder)
+                .Returns(new MetaBuilder());
+
+            _pageManager = new PageManager();
+            _jsonApiContextMock
+                .Setup(m => m.PageManager)
+                .Returns(_pageManager);
+
+            _jsonApiContextMock
+                .Setup(m => m.BasePath)
+                .Returns("localhost");
+
+            _jsonApiContextMock
+                .Setup(m => m.RequestEntity)
+                .Returns(_options.ContextGraph.GetContextEntity(typeof(Model)));
+        }
+
+        [Fact]
+        public void Includes_Paging_Links_By_Default()
+        {
+            // arrange
+            _pageManager.PageSize = 1;
+            _pageManager.TotalRecords = 1;
+            _pageManager.CurrentPage = 1;
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model();
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            Assert.NotNull(document.Links);
+            Assert.NotNull(document.Links.Last);
         }
 
-        [Fact]
-        public void IndependentIdentifier__Included_In_HasOne_Relationships_By_Default()
-        {
-            // arrange
-            const string relatedTypeName = "related-models";
-            const string relationshipName = "related-model";
-            const int relatedId = 1;
-            _jsonApiContextMock
-                .Setup(m => m.ContextGraph)
-                .Returns(_options.ContextGraph);
-
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-            var entity = new Model
+        [Fact]
+        public void Page_Links_Can_Be_Disabled_Globally()
+        {
+            // arrange
+            _pageManager.PageSize = 1;
+            _pageManager.TotalRecords = 1;
+            _pageManager.CurrentPage = 1;
+
+            _options.BuildContextGraph(builder => builder.DocumentLinks = Link.None);
+
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model();
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            Assert.Null(document.Links);
+        }
+
+        [Fact]
+        public void Related_Links_Can_Be_Disabled()
+        {
+            // arrange
+            _pageManager.PageSize = 1;
+            _pageManager.TotalRecords = 1;
+            _pageManager.CurrentPage = 1;
+
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model();
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            Assert.Null(document.Data.Relationships["related-model"].Links);
+        }
+
+        [Fact]
+        public void Related_Data_Included_In_Relationships_By_Default()
+        {
+            // arrange
+            const string relatedTypeName = "related-models";
+            const string relationshipName = "related-model";
+            const int relatedId = 1;
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model
             {
-                RelatedModelId = relatedId
-            };
-
-            // act
-            var document = documentBuilder.Build(entity);
-
-            // assert
-            var relationshipData = document.Data.Relationships[relationshipName];
-            Assert.NotNull(relationshipData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.NotNull(relationshipData.SingleData);
-            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
-            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
-        }
-
-        [Fact]
-        public void Build_Can_Build_Arrays()
-        {
-            var entities = new[] { new Model() };
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-
-            var documents = documentBuilder.Build(entities);
-
-            Assert.Equal(1, documents.Data.Count);
-        }
-
-        [Fact]
-        public void Build_Can_Build_CustomIEnumerables()
-        {
-            var entities = new Models(new[] { new Model() });
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
-
-            var documents = documentBuilder.Build(entities);
-
-            Assert.Equal(1, documents.Data.Count);
-        }
-
-
-        [Theory]
-        [InlineData(null, null, true)]
-        [InlineData(false, null, true)]
-        [InlineData(true, null, false)]
-        [InlineData(null, "foo", true)]
-        [InlineData(false, "foo", true)]
-        [InlineData(true, "foo", true)]
-        public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
-            string attributeValue,
-            bool resultContainsAttribute)
-        {
-            var documentBuilderBehaviourMock = new Mock<IDocumentBuilderOptionsProvider>();
-            if (omitNullValuedAttributes.HasValue)
-            {
-                documentBuilderBehaviourMock.Setup(m => m.GetDocumentBuilderOptions())
-                    .Returns(new DocumentBuilderOptions(omitNullValuedAttributes.Value));
-            }
-            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, null, omitNullValuedAttributes.HasValue ? documentBuilderBehaviourMock.Object : null);
-            var document = documentBuilder.Build(new Model() { StringProperty = attributeValue });
-
-            Assert.Equal(resultContainsAttribute, document.Data.Attributes.ContainsKey("StringProperty"));
-        }
-
-        private class Model : Identifiable
-        {
-            [HasOne("related-model", Link.None)]
-            public RelatedModel RelatedModel { get; set; }
-            public int RelatedModelId { get; set; }
-            [Attr("StringProperty")]
-            public string StringProperty { get; set; }
-
-        }
-
-        private class RelatedModel : Identifiable
-        {
-            [HasMany("models")]
-            public List<Model> Models { get; set; }
-        }
-
-        private class Models : IEnumerable<Model>
-        {
-            private readonly IEnumerable<Model> models;
-
-            public Models(IEnumerable<Model> models)
-            {
-                this.models = models;
-            }
-
-            public IEnumerator<Model> GetEnumerator()
-            {
-                return models.GetEnumerator();
-            }
-
-            IEnumerator IEnumerable.GetEnumerator()
-            {
-                return models.GetEnumerator();
-            }
-        }
-    }
-}
+                RelatedModel = new RelatedModel
+                {
+                    Id = relatedId
+                }
+            };
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            var relationshipData = document.Data.Relationships[relationshipName];
+            Assert.NotNull(relationshipData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
+            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
+        }
+
+        [Fact]
+        public void IndependentIdentifier__Included_In_HasOne_Relationships_By_Default()
+        {
+            // arrange
+            const string relatedTypeName = "related-models";
+            const string relationshipName = "related-model";
+            const int relatedId = 1;
+            _jsonApiContextMock
+                .Setup(m => m.ContextGraph)
+                .Returns(_options.ContextGraph);
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+            var entity = new Model
+            {
+                RelatedModelId = relatedId
+            };
+
+            // act
+            var document = documentBuilder.Build(entity);
+
+            // assert
+            var relationshipData = document.Data.Relationships[relationshipName];
+            Assert.NotNull(relationshipData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.NotNull(relationshipData.SingleData);
+            Assert.Equal(relatedId.ToString(), relationshipData.SingleData.Id);
+            Assert.Equal(relatedTypeName, relationshipData.SingleData.Type);
+        }
+
+        [Fact]
+        public void Build_Can_Build_Arrays()
+        {
+            var entities = new[] { new Model() };
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+
+            var documents = documentBuilder.Build(entities);
+
+            Assert.Equal(1, documents.Data.Count);
+        }
+
+        [Fact]
+        public void Build_Can_Build_CustomIEnumerables()
+        {
+            var entities = new Models(new[] { new Model() });
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object);
+
+            var documents = documentBuilder.Build(entities);
+
+            Assert.Equal(1, documents.Data.Count);
+        }
+
+
+        [Theory]
+        [InlineData(null, null, true)]
+        [InlineData(false, null, true)]
+        [InlineData(true, null, false)]
+        [InlineData(null, "foo", true)]
+        [InlineData(false, "foo", true)]
+        [InlineData(true, "foo", true)]
+        public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
+            string attributeValue,
+            bool resultContainsAttribute)
+        {
+            var documentBuilderBehaviourMock = new Mock<IDocumentBuilderOptionsProvider>();
+            if (omitNullValuedAttributes.HasValue)
+            {
+                documentBuilderBehaviourMock.Setup(m => m.GetDocumentBuilderOptions())
+                    .Returns(new DocumentBuilderOptions(omitNullValuedAttributes.Value));
+            }
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, null, omitNullValuedAttributes.HasValue ? documentBuilderBehaviourMock.Object : null);
+            var document = documentBuilder.Build(new Model() { StringProperty = attributeValue });
+
+            Assert.Equal(resultContainsAttribute, document.Data.Attributes.ContainsKey("StringProperty"));
+        }
+
+        private class Model : Identifiable
+        {
+            [HasOne("related-model", Link.None)]
+            public RelatedModel RelatedModel { get; set; }
+            public int RelatedModelId { get; set; }
+            [Attr("StringProperty")]
+            public string StringProperty { get; set; }
+
+        }
+
+        private class RelatedModel : Identifiable
+        {
+            [HasMany("models")]
+            public List<Model> Models { get; set; }
+        }
+
+        private class Models : IEnumerable<Model>
+        {
+            private readonly IEnumerable<Model> models;
+
+            public Models(IEnumerable<Model> models)
+            {
+                this.models = models;
+            }
+
+            public IEnumerator<Model> GetEnumerator()
+            {
+                return models.GetEnumerator();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return models.GetEnumerator();
+            }
+        }
+    }
+}
diff --git a/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
index 4fe2f09ff1..1b00c5aaa1 100644
--- a/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
+++ b/test/UnitTests/Extensions/IServiceCollectionExtensionsTests.cs
@@ -25,10 +25,7 @@ public void AddJsonApiInternals_Adds_All_Required_Services()
             var services = new ServiceCollection();
             var jsonApiOptions = new JsonApiOptions();
 
-            services.AddDbContext<AppDbContext>(options =>
-            {
-                options.UseInMemoryDatabase();
-            }, ServiceLifetime.Transient);
+            services.AddDbContext<AppDbContext>(options => options.UseInMemoryDatabase("UnitTestDb"), ServiceLifetime.Transient);
 
             // act
             services.AddJsonApiInternals<AppDbContext>(jsonApiOptions);

From 49468edc4866875bba6c41e39fb92f509c59514c Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 8 Jun 2018 23:14:35 -0500
Subject: [PATCH 175/227] fix(JsonApiDeSerializer): null refs

---
 .../Serialization/JsonApiDeSerializer.cs      | 21 +++++++++++--------
 .../Serialization/JsonApiDeSerializerTests.cs |  2 --
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index da206e4930..45d77c0f77 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -209,20 +209,23 @@ private object SetHasOneRelationship(object entity,
 
                 var foreignKey = attr.IdentifiablePropertyName;
                 var entityProperty = entityProperties.FirstOrDefault(p => p.Name == foreignKey);
-                if (entityProperty == null)
+                if (entityProperty == null && rio != null)
                     throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a foreign key property '{foreignKey}' for has one relationship '{attr.InternalRelationshipName}'");
 
-                // e.g. PATCH /articles
-                // {... { "relationships":{ "Owner": { "data" :null } } } }
-                if (rio == null && Nullable.GetUnderlyingType(entityProperty.PropertyType) == null)
-                    throw new JsonApiException(400, $"Cannot set required relationship identifier '{attr.IdentifiablePropertyName}' to null.");
+                if (entityProperty != null)
+                {
+                    // e.g. PATCH /articles
+                    // {... { "relationships":{ "Owner": { "data" :null } } } }
+                    if (rio == null && Nullable.GetUnderlyingType(entityProperty.PropertyType) == null)
+                        throw new JsonApiException(400, $"Cannot set required relationship identifier '{attr.IdentifiablePropertyName}' to null.");
 
-                var newValue = rio?.Id ?? null;
-                var convertedValue = TypeHelper.ConvertType(newValue, entityProperty.PropertyType);
+                    var newValue = rio?.Id ?? null;
+                    var convertedValue = TypeHelper.ConvertType(newValue, entityProperty.PropertyType);
 
-                _jsonApiContext.RelationshipsToUpdate[relationshipAttr] = convertedValue;
+                    _jsonApiContext.RelationshipsToUpdate[relationshipAttr] = convertedValue;
 
-                entityProperty.SetValue(entity, convertedValue);
+                    entityProperty.SetValue(entity, convertedValue);
+                }
             }
 
             return entity;
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index 0b80d3a25a..ec34d87d24 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -345,8 +345,6 @@ private class Dependent : Identifiable
             public int IndependentId { get; set; }
         }
 
-
-
         [Fact]
         public void Can_Deserialize_Object_With_HasManyRelationship()
         {

From 013197a7060e46789e4cfd042844ad101f3fcfa0 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 8 Jun 2018 23:16:16 -0500
Subject: [PATCH 176/227] chore(csproj): bump package version

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index eb649ed5dc..f296ef318f 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.2.4</VersionPrefix>
+    <VersionPrefix>2.2.5/VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From d76c6000fffdb384a510233206e4136d4e4bc68b Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 8 Jun 2018 23:21:02 -0500
Subject: [PATCH 177/227] fix(csproj): syntax error

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index f296ef318f..4f52a23002 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.2.5/VersionPrefix>
+    <VersionPrefix>2.2.5</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From 22e742de2f66524b03a5e29edf0638935fe57189 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Sun, 10 Jun 2018 12:38:43 -0500
Subject: [PATCH 178/227] test(spec): can create hasOne relationship with
 resource

---
 .../Acceptance/Spec/CreatingDataTests.cs      | 61 ++++++++++++++++++-
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
index 2c71275473..015d79cdbd 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs
@@ -106,7 +106,7 @@ public async Task Cannot_Create_Entity_With_Client_Generate_Id()
                     attributes = new
                     {
                         description = todoItem.Description,
-                        ordinal = todoItem.Ordinal, 
+                        ordinal = todoItem.Ordinal,
                         createdDate = DateTime.Now
                     }
                 }
@@ -174,7 +174,7 @@ public async Task Can_Create_Guid_Identifiable_Entity_With_Client_Defined_Id_If_
             var httpMethod = new HttpMethod("POST");
             var server = new TestServer(builder);
             var client = server.CreateClient();
-            
+
             var context = _fixture.GetService<AppDbContext>();
 
             var owner = new JsonApiDotNetCoreExample.Models.Person();
@@ -285,6 +285,63 @@ public async Task Can_Create_And_Set_HasMany_Relationships()
             Assert.NotEmpty(contextCollection.TodoItems);
         }
 
+        [Fact]
+        public async Task Can_Create_And_Set_HasOne_Relationships()
+        {
+            // arrange
+            var builder = new WebHostBuilder()
+                .UseStartup<Startup>();
+            var httpMethod = new HttpMethod("POST");
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+
+            var context = _fixture.GetService<AppDbContext>();
+
+            var todoItem = new TodoItem();
+            var owner = new JsonApiDotNetCoreExample.Models.Person();
+            context.People.Add(owner);
+            await context.SaveChangesAsync();
+
+            var route = "/api/v1/todo-items";
+            var request = new HttpRequestMessage(httpMethod, route);
+            var content = new
+            {
+                data = new
+                {
+                    type = "todo-items",
+                    relationships = new Dictionary<string, dynamic>
+                    {
+                        {  "owner",  new {
+                            data = new
+                            {
+                                type = "people",
+                                id = owner.Id.ToString()
+                            }
+                        } }
+                    }
+                }
+            };
+
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // act
+            var response = await client.SendAsync(request);
+            var body = await response.Content.ReadAsStringAsync();
+
+            // assert
+            Assert.Equal(HttpStatusCode.Created, response.StatusCode);
+            var deserializedBody = (TodoItem)_fixture.GetService<IJsonApiDeSerializer>().Deserialize(body);
+            var newId = deserializedBody.Id;
+
+            context = _fixture.GetService<AppDbContext>();
+            var todoItemResult = context.TodoItems
+                .Include(c => c.Owner)
+                .SingleOrDefault(c => c.Id == newId);
+
+            Assert.Equal(owner.Id, todoItemResult.OwnerId);
+        }
+
         [Fact]
         public async Task ShouldReceiveLocationHeader_InResponse()
         {

From df7cc0f04924c4933df8d4bcc742f099a4baae29 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 11 Jun 2018 21:33:09 -0500
Subject: [PATCH 179/227] docs(*): add xml comments

---
 .../IDocumentBuilderOptionsProvider.cs        |  6 +--
 .../NullAttributeResponseBehavior.cs          | 25 +++++++--
 src/JsonApiDotNetCore/Models/AttrAttribute.cs | 53 ++++++++++++++++++-
 .../Models/HasManyAttribute.cs                | 26 ++++++++-
 .../Services/QueryComposer.cs                 |  5 +-
 5 files changed, 100 insertions(+), 15 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/IDocumentBuilderOptionsProvider.cs b/src/JsonApiDotNetCore/Builders/IDocumentBuilderOptionsProvider.cs
index d8effd4fe3..fe014bced5 100644
--- a/src/JsonApiDotNetCore/Builders/IDocumentBuilderOptionsProvider.cs
+++ b/src/JsonApiDotNetCore/Builders/IDocumentBuilderOptionsProvider.cs
@@ -1,11 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
 namespace JsonApiDotNetCore.Builders
 {
     public interface IDocumentBuilderOptionsProvider
     {
-        DocumentBuilderOptions GetDocumentBuilderOptions(); 
+        DocumentBuilderOptions GetDocumentBuilderOptions();
     }
 }
diff --git a/src/JsonApiDotNetCore/Configuration/NullAttributeResponseBehavior.cs b/src/JsonApiDotNetCore/Configuration/NullAttributeResponseBehavior.cs
index 1b10140f5e..125d38b5fc 100644
--- a/src/JsonApiDotNetCore/Configuration/NullAttributeResponseBehavior.cs
+++ b/src/JsonApiDotNetCore/Configuration/NullAttributeResponseBehavior.cs
@@ -1,19 +1,34 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
 namespace JsonApiDotNetCore.Configuration
 {
+    /// <summary>
+    /// Allows null attributes to be ommitted from the response payload
+    /// </summary>
     public struct NullAttributeResponseBehavior
     {
+        /// <param name="omitNullValuedAttributes">Do not serialize null attributes</param>
+        /// <param name="allowClientOverride">
+        /// Allow clients to override the serialization behavior through a query parmeter.
+        /// <example>
+        /// ```
+        /// GET /articles?omitNullValuedAttributes=true
+        /// ```
+        /// </example>
+        /// </param>
         public NullAttributeResponseBehavior(bool omitNullValuedAttributes = false, bool allowClientOverride = false)
         {
             OmitNullValuedAttributes = omitNullValuedAttributes;
             AllowClientOverride = allowClientOverride;
         }
 
+        /// <summary>
+        /// Do not include null attributes in the response payload.
+        /// </summary>
         public bool OmitNullValuedAttributes { get; }
+
+        /// <summary>
+        /// Allows clients to specify a `omitNullValuedAttributes` boolean query param to control
+        /// serialization behavior.
+        /// </summary>
         public bool AllowClientOverride { get; }
-        // ...
     }
 }
diff --git a/src/JsonApiDotNetCore/Models/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
index db61cb56ea..e38b47abec 100644
--- a/src/JsonApiDotNetCore/Models/AttrAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
@@ -5,6 +5,26 @@ namespace JsonApiDotNetCore.Models
 {
     public class AttrAttribute : Attribute
     {
+        /// <summary>
+        /// Defines a public attribute exposed by the API
+        /// </summary>
+        /// 
+        /// <param name="publicName">How this attribute is exposed through the API</param>
+        /// <param name="isImmutable">Prevent PATCH requests from updating the value</param>
+        /// <param name="isFilterable">Prevent filters on this attribute</param>
+        /// <param name="isSortable">Prevent this attribute from being sorted by</param>
+        /// 
+        /// <example>
+        /// 
+        /// <code>
+        /// public class Author : Identifiable
+        /// {
+        ///     [Attr("name")]
+        ///     public string Name { get; set; }
+        /// }
+        /// </code>
+        /// 
+        /// </example>
         public AttrAttribute(string publicName, bool isImmutable = false, bool isFilterable = true, bool isSortable = true)
         {
             PublicAttributeName = publicName;
@@ -20,20 +40,51 @@ internal AttrAttribute(string publicName, string internalName, bool isImmutable
             IsImmutable = isImmutable;
         }
 
+        /// <summary>
+        /// How this attribute is exposed through the API
+        /// </summary>
         public string PublicAttributeName { get; }
+
+        /// <summary>
+        /// The internal property name this attribute belongs to.
+        /// </summary>
         public string InternalAttributeName { get; internal set; }
+
+        /// <summary>
+        /// Prevents PATCH requests from updating the value.
+        /// </summary>
         public bool IsImmutable { get; }
+
+        /// <summary>
+        /// Whether or not this attribute can be filtered on via a query string filters.
+        /// Attempts to filter on an attribute with `IsFilterable == false` will return
+        /// an HTTP 400 response.
+        /// </summary>
         public bool IsFilterable { get; }
+
+        /// <summary>
+        /// Whether or not this attribute can be sorted on via a query string sort.
+        /// Attempts to filter on an attribute with `IsSortable == false` will return
+        /// an HTTP 400 response.
+        /// </summary>
         public bool IsSortable { get; }
 
+        /// <summary>
+        /// Get the value of the attribute for the given object.
+        /// Returns null if the attribute does not belong to the
+        /// provided object.
+        /// </summary>
         public object GetValue(object entity)
         {
             return entity
                 .GetType()
                 .GetProperty(InternalAttributeName)
-                .GetValue(entity);
+                ?.GetValue(entity);
         }
 
+        /// <summary>
+        /// Sets the value of the attribute on the given object.
+        /// </summary>
         public void SetValue(object entity, object newValue)
         {
             var propertyInfo = entity
diff --git a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
index c2d7594400..877df29146 100644
--- a/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/HasManyAttribute.cs
@@ -2,16 +2,40 @@ namespace JsonApiDotNetCore.Models
 {
     public class HasManyAttribute : RelationshipAttribute
     {
+        /// <summary>
+        /// Create a HasMany relational link to another entity
+        /// </summary>
+        /// 
+        /// <param name="publicName">The relationship name as exposed by the API</param>
+        /// <param name="documentLinks">Which links are available. Defaults to <see cref="Link.All"/></param>
+        /// <param name="canInclude">Whether or not this relationship can be included using the <c>?include=public-name</c> query string</param>
+        /// 
+        /// <example>
+        /// 
+        /// <code>
+        /// public class Author : Identifiable 
+        /// {
+        ///     [HasMany("articles"]
+        ///     public virtual List<Article> Articles { get; set; }
+        /// }
+        /// </code>
+        /// 
+        /// </example>
         public HasManyAttribute(string publicName, Link documentLinks = Link.All, bool canInclude = true)
         : base(publicName, documentLinks, canInclude)
         { }
 
+        /// <summary>
+        /// Sets the value of the property identified by this attribute
+        /// </summary>
+        /// <param name="entity">The target object</param>
+        /// <param name="newValue">The new property value</param>
         public override void SetValue(object entity, object newValue)
         {
             var propertyInfo = entity
                 .GetType()
                 .GetProperty(InternalRelationshipName);
-            
+
             propertyInfo.SetValue(entity, newValue);
         }
     }
diff --git a/src/JsonApiDotNetCore/Services/QueryComposer.cs b/src/JsonApiDotNetCore/Services/QueryComposer.cs
index 8e0819a438..e365811704 100644
--- a/src/JsonApiDotNetCore/Services/QueryComposer.cs
+++ b/src/JsonApiDotNetCore/Services/QueryComposer.cs
@@ -1,6 +1,5 @@
 using System.Collections.Generic;
 using JsonApiDotNetCore.Internal.Query;
-using Microsoft.Extensions.Logging;
 
 namespace JsonApiDotNetCore.Services
 {
@@ -14,8 +13,8 @@ public class QueryComposer : IQueryComposer
         public string Compose(IJsonApiContext jsonApiContext)
         {
             string result = "";
-            if(jsonApiContext != null && jsonApiContext.QuerySet != null)
-            {                
+            if (jsonApiContext != null && jsonApiContext.QuerySet != null)
+            {
                 List<FilterQuery> filterQueries = jsonApiContext.QuerySet.Filters;
                 if (filterQueries.Count > 0)
                 {

From 67c310299d0088f4dde87f86e9564afede850bc1 Mon Sep 17 00:00:00 2001
From: Bj <btecu@outlook.com>
Date: Mon, 11 Jun 2018 23:07:19 -0400
Subject: [PATCH 180/227] Make `AddJsonApi` chainable

---
 .../JsonApiDotNetCoreExample/Startup.cs       | 23 ++++++--------
 .../IServiceCollectionExtensions.cs           | 14 +++++----
 .../Helpers/Startups/MetaStartup.cs           | 31 +++++++------------
 3 files changed, 30 insertions(+), 38 deletions(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/Startup.cs b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
index 1388004a55..378a948a61 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Startup.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
@@ -29,19 +29,16 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
         {
             var loggerFactory = new LoggerFactory();
             loggerFactory.AddConsole(LogLevel.Trace);
-            services.AddSingleton<ILoggerFactory>(loggerFactory);
 
-            services.AddDbContext<AppDbContext>(options =>
-            {
-                options.UseNpgsql(GetDbConnectionString());
-            }, ServiceLifetime.Transient);
-
-            services.AddJsonApi<AppDbContext>(opt =>
-            {
-                opt.Namespace = "api/v1";
-                opt.DefaultPageSize = 5;
-                opt.IncludeTotalRecordCount = true;
-            });
+            services
+                .AddSingleton<ILoggerFactory>(loggerFactory)
+                .AddDbContext<AppDbContext>(options =>
+                    options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient)
+                .AddJsonApi<AppDbContext>(options => {
+                    options.Namespace = "api/v1";
+                    options.DefaultPageSize = 5;
+                    options.IncludeTotalRecordCount = true;
+                });
 
             var provider = services.BuildServiceProvider();
             var appContext = provider.GetRequiredService<AppDbContext>();
@@ -67,4 +64,4 @@ public virtual void Configure(
 
         public string GetDbConnectionString() => Config["Data:DefaultConnection"];
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 807d21c018..217b5f077b 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -20,21 +20,21 @@ namespace JsonApiDotNetCore.Extensions
     // ReSharper disable once InconsistentNaming
     public static class IServiceCollectionExtensions
     {
-        public static void AddJsonApi<TContext>(this IServiceCollection services)
+        public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services)
             where TContext : DbContext
         {
             var mvcBuilder = services.AddMvc();
-            AddJsonApi<TContext>(services, (opt) => { }, mvcBuilder);
+            return AddJsonApi<TContext>(services, (opt) => { }, mvcBuilder);
         }
 
-        public static void AddJsonApi<TContext>(this IServiceCollection services, Action<JsonApiOptions> options)
+        public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services, Action<JsonApiOptions> options)
             where TContext : DbContext
         {
             var mvcBuilder = services.AddMvc();
-            AddJsonApi<TContext>(services, options, mvcBuilder);
+            return AddJsonApi<TContext>(services, options, mvcBuilder);
         }
 
-        public static void AddJsonApi<TContext>(this IServiceCollection services,
+        public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services,
            Action<JsonApiOptions> options,
            IMvcBuilder mvcBuilder) where TContext : DbContext
         {
@@ -52,9 +52,10 @@ public static void AddJsonApi<TContext>(this IServiceCollection services,
                 });
 
             AddJsonApiInternals<TContext>(services, config);
+            return services;
         }
 
-        public static void AddJsonApi(this IServiceCollection services,
+        public static IServiceCollection AddJsonApi(this IServiceCollection services,
             Action<JsonApiOptions> options,
             IMvcBuilder mvcBuilder)
         {
@@ -70,6 +71,7 @@ public static void AddJsonApi(this IServiceCollection services,
                 });
 
             AddJsonApiInternals(services, config);
+            return services;
         }
 
         public static void AddJsonApiInternals<TContext>(
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/MetaStartup.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/MetaStartup.cs
index 0001878a50..df32a1223a 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/MetaStartup.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/MetaStartup.cs
@@ -20,25 +20,18 @@ public MetaStartup(IHostingEnvironment env)
         public override IServiceProvider ConfigureServices(IServiceCollection services)
         {
             var loggerFactory = new LoggerFactory();
-
-            loggerFactory
-              .AddConsole(LogLevel.Trace);
-
-            services.AddSingleton<ILoggerFactory>(loggerFactory);
-
-            services.AddDbContext<AppDbContext>(options =>
-            {
-                options.UseNpgsql(GetDbConnectionString());
-            }, ServiceLifetime.Transient);
-
-            services.AddJsonApi<AppDbContext>(opt =>
-            {
-                opt.Namespace = "api/v1";
-                opt.DefaultPageSize = 5;
-                opt.IncludeTotalRecordCount = true;
-            });
-
-            services.AddScoped<IRequestMeta, MetaService>();
+            loggerFactory.AddConsole(LogLevel.Trace);
+
+            services
+                .AddSingleton<ILoggerFactory>(loggerFactory)
+                .AddDbContext<AppDbContext>(options => 
+                    options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient)
+                .AddJsonApi<AppDbContext>(options => {
+                    options.Namespace = "api/v1";
+                    options.DefaultPageSize = 5;
+                    options.IncludeTotalRecordCount = true;
+                })
+                .AddScoped<IRequestMeta, MetaService>();
 
             return services.BuildServiceProvider();
         }

From a3f6d5fbd4c7fe3f6bf56a90c9975ccaea44a2d2 Mon Sep 17 00:00:00 2001
From: Bj <btecu@outlook.com>
Date: Mon, 11 Jun 2018 23:10:35 -0400
Subject: [PATCH 181/227] Use `MvcCore` instead of `Mvc`

---
 .travis.yml                                            |  4 ++--
 .../Controllers/Restricted/ReadOnlyController.cs       |  8 ++++----
 .../Controllers/TestValuesController.cs                |  2 +-
 .../Controllers/TodoItemsCustomController.cs           |  2 +-
 src/Examples/NoEntityFrameworkExample/Startup.cs       |  4 ++--
 src/Examples/ReportsExample/ReportsExample.csproj      |  2 +-
 src/Examples/ReportsExample/Startup.cs                 |  2 +-
 .../Controllers/JsonApiControllerMixin.cs              |  2 +-
 .../Controllers/JsonApiOperationsController.cs         |  2 +-
 .../Extensions/IServiceCollectionExtensions.cs         | 10 +++++-----
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj         |  3 ++-
 11 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 7ac38bba9f..9c5e937589 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,12 @@
 language: csharp
 dist: trusty
 sudo: required
-services: 
+services:
  - postgresql
 before_script:
   - psql -c 'create database JsonApiDotNetCoreExample;' -U postgres
 mono: none
-dotnet: 2.1.105 # https://www.microsoft.com/net/download/linux
+dotnet: 2.1.300 # https://www.microsoft.com/net/download/linux
 branches:
   only:
     - master
diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/Restricted/ReadOnlyController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/Restricted/ReadOnlyController.cs
index 57fafc8fc6..2515b1ea7a 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Controllers/Restricted/ReadOnlyController.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/Restricted/ReadOnlyController.cs
@@ -5,7 +5,7 @@ namespace JsonApiDotNetCoreExample.Controllers.Restricted
 {
     [Route("[controller]")]
     [HttpReadOnly]
-    public class ReadOnlyController : Controller
+    public class ReadOnlyController : ControllerBase
     {
         [HttpGet]
         public IActionResult Get() => Ok();
@@ -22,7 +22,7 @@ public class ReadOnlyController : Controller
 
     [Route("[controller]")]
     [NoHttpPost]
-    public class NoHttpPostController : Controller
+    public class NoHttpPostController : ControllerBase
     {
         [HttpGet]
         public IActionResult Get() => Ok();
@@ -39,7 +39,7 @@ public class NoHttpPostController : Controller
 
     [Route("[controller]")]
     [NoHttpPatch]
-    public class NoHttpPatchController : Controller
+    public class NoHttpPatchController : ControllerBase
     {
         [HttpGet]
         public IActionResult Get() => Ok();
@@ -56,7 +56,7 @@ public class NoHttpPatchController : Controller
 
     [Route("[controller]")]
     [NoHttpDelete]
-    public class NoHttpDeleteController : Controller
+    public class NoHttpDeleteController : ControllerBase
     {
         [HttpGet]
         public IActionResult Get() => Ok();
diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/TestValuesController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/TestValuesController.cs
index 3443d34b74..a29295c426 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Controllers/TestValuesController.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/TestValuesController.cs
@@ -3,7 +3,7 @@
 namespace JsonApiDotNetCoreExample.Controllers
 {
     [Route("[controller]")]
-    public class TestValuesController : Controller
+    public class TestValuesController : ControllerBase
     {
         [HttpGet]
         public IActionResult Get()
diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs
index de784c129a..fc25f8396e 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs
@@ -33,7 +33,7 @@ public CustomJsonApiController(
     }
 
     public class CustomJsonApiController<T, TId>
-    : Controller where T : class, IIdentifiable<TId>
+    : ControllerBase where T : class, IIdentifiable<TId>
     {
         private readonly ILogger _logger;
         private readonly IResourceService<T, TId> _resourceService;
diff --git a/src/Examples/NoEntityFrameworkExample/Startup.cs b/src/Examples/NoEntityFrameworkExample/Startup.cs
index dfba27ddd9..86eee500c9 100755
--- a/src/Examples/NoEntityFrameworkExample/Startup.cs
+++ b/src/Examples/NoEntityFrameworkExample/Startup.cs
@@ -1,4 +1,4 @@
-using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Services;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
@@ -31,7 +31,7 @@ public Startup(IHostingEnvironment env)
         public virtual IServiceProvider ConfigureServices(IServiceCollection services)
         {
             // Add framework services.
-            var mvcBuilder = services.AddMvc();
+            var mvcBuilder = services.AddMvcCore();
 
             services.AddJsonApi(options => {
                 options.Namespace = "api/v1";
diff --git a/src/Examples/ReportsExample/ReportsExample.csproj b/src/Examples/ReportsExample/ReportsExample.csproj
index bd4b402071..48df3ea2c8 100644
--- a/src/Examples/ReportsExample/ReportsExample.csproj
+++ b/src/Examples/ReportsExample/ReportsExample.csproj
@@ -13,7 +13,7 @@
 
   <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
-    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftLoggingVersion)" />
     <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
     <PackageReference Include="Npgsql" Version="$(NpgsqlVersion)" />
diff --git a/src/Examples/ReportsExample/Startup.cs b/src/Examples/ReportsExample/Startup.cs
index 72710681b9..fe476c0406 100644
--- a/src/Examples/ReportsExample/Startup.cs
+++ b/src/Examples/ReportsExample/Startup.cs
@@ -25,7 +25,7 @@ public Startup(IHostingEnvironment env)
 
         public virtual void ConfigureServices(IServiceCollection services)
         {
-            var mvcBuilder = services.AddMvc();
+            var mvcBuilder = services.AddMvcCore();
             services.AddJsonApi(opt =>
             {
                 opt.BuildContextGraph(builder =>
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
index 6fff3a22c8..840422eb6c 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
@@ -5,7 +5,7 @@
 
 namespace JsonApiDotNetCore.Controllers
 {
-    public abstract class JsonApiControllerMixin : Controller
+    public abstract class JsonApiControllerMixin : ControllerBase
     {
         protected IActionResult UnprocessableEntity()
         {
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
index c3b667bc7d..f6db9f0d06 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs
@@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Controllers
     /// <summary>
     /// A controller to be used for bulk operations as defined in the json:api 1.1 specification
     /// </summary>
-    public class JsonApiOperationsController : Controller
+    public class JsonApiOperationsController : ControllerBase
     {
         private readonly IOperationsProcessor _operationsProcessor;
 
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 217b5f077b..5e8eeefdd1 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -23,20 +23,20 @@ public static class IServiceCollectionExtensions
         public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services)
             where TContext : DbContext
         {
-            var mvcBuilder = services.AddMvc();
-            return AddJsonApi<TContext>(services, (opt) => { }, mvcBuilder);
+            var mvcBuilder = services.AddMvcCore();
+            return AddJsonApi<TContext>(services, opt => { }, mvcBuilder);
         }
 
         public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services, Action<JsonApiOptions> options)
             where TContext : DbContext
         {
-            var mvcBuilder = services.AddMvc();
+            var mvcBuilder = services.AddMvcCore();
             return AddJsonApi<TContext>(services, options, mvcBuilder);
         }
 
         public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services,
            Action<JsonApiOptions> options,
-           IMvcBuilder mvcBuilder) where TContext : DbContext
+           IMvcCoreBuilder mvcBuilder) where TContext : DbContext
         {
             var config = new JsonApiOptions();
 
@@ -57,7 +57,7 @@ public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection se
 
         public static IServiceCollection AddJsonApi(this IServiceCollection services,
             Action<JsonApiOptions> options,
-            IMvcBuilder mvcBuilder)
+            IMvcCoreBuilder mvcBuilder)
         {
             var config = new JsonApiOptions();
 
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 4f52a23002..960f0f84ea 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -19,11 +19,12 @@
   <ItemGroup>
     <PackageReference Include="Ben.Demystifier" Version="0.1.0" />
     <PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
-    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
     <PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftLoggingVersion)" />
     <PackageReference Include="System.Memory" Version="4.5.0-preview2-26406-04" />
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
+    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
   </ItemGroup>
 
   <!-- 

From d7a6346a3fe51ec6977e11ff9ac188736b8bef3c Mon Sep 17 00:00:00 2001
From: Bj <btecu@outlook.com>
Date: Mon, 11 Jun 2018 23:10:58 -0400
Subject: [PATCH 182/227] Update dependencies

---
 Directory.Build.props                         | 27 +++++++++----------
 benchmarks/Benchmarks.csproj                  |  2 +-
 .../20180327120810_initial.Designer.cs        |  3 ++-
 .../Migrations/20180327120810_initial.cs      |  3 ++-
 .../Migrations/AppDbContextModelSnapshot.cs   |  3 ++-
 .../NoEntityFrameworkExample.csproj           |  2 +-
 .../ReportsExample/ReportsExample.csproj      |  2 +-
 .../JsonApiDotNetCore.csproj                  |  6 ++---
 .../JsonApiDotNetCoreExampleTests.csproj      |  4 +--
 .../NoEntityFrameworkTests.csproj             |  2 +-
 .../OperationsExampleTests.csproj             |  2 +-
 test/UnitTests/UnitTests.csproj               |  2 +-
 12 files changed, 30 insertions(+), 28 deletions(-)

diff --git a/Directory.Build.props b/Directory.Build.props
index 346835dd6c..0d034e0c5d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -4,28 +4,27 @@
     <NetCoreAppVersion>netcoreapp2.0</NetCoreAppVersion>
     <NetStandardVersion>netstandard2.0</NetStandardVersion>
 
-    <AspNetCoreVersion>2.0.1</AspNetCoreVersion>
+    <AspNetCoreVersion>2.1.0</AspNetCoreVersion>
 
-    <MicrosoftLoggingVersion>2.0.0</MicrosoftLoggingVersion>
-    <MicrosoftConfigurationVersion>2.0.0</MicrosoftConfigurationVersion>
-    <MicrosoftOptionsVersion>2.0.0</MicrosoftOptionsVersion>
+    <MicrosoftLoggingVersion>2.1.0</MicrosoftLoggingVersion>
+    <MicrosoftConfigurationVersion>2.1.0</MicrosoftConfigurationVersion>
+    <MicrosoftOptionsVersion>2.1.0</MicrosoftOptionsVersion>
 
-    <EFCoreVersion>2.0.1</EFCoreVersion>
-    <EFCoreToolsVersion>2.0.1</EFCoreToolsVersion>
+    <EFCoreVersion>2.1.0</EFCoreVersion>
+    <EFCoreToolsVersion>2.1.0</EFCoreToolsVersion>
 
-    <NpgsqlVersion>3.2.6</NpgsqlVersion>
-    <NpgsqlPostgreSQLVersion>2.0.0</NpgsqlPostgreSQLVersion>
+    <NpgsqlVersion>4.0.0</NpgsqlVersion>
+    <NpgsqlPostgreSQLVersion>2.1.0</NpgsqlPostgreSQLVersion>
 
-    <TuplesVersion>4.4.0</TuplesVersion>
+    <TuplesVersion>4.5.0</TuplesVersion>
   </PropertyGroup>
 
   <!-- Test Project Dependencies -->
   <PropertyGroup>
-    <TestSdkVersion>15.3.0-preview-20170427-09</TestSdkVersion>
-    <TestHostVersion>1.1.2</TestHostVersion>
-    <XUnitVersion>2.3.0-beta3-build3705</XUnitVersion>
-    <BogusVersion>15.0.3</BogusVersion>
-    <MoqVersion>4.7.99</MoqVersion>
+    <TestSdkVersion>15.7.2</TestSdkVersion>
+    <XUnitVersion>2.3.1</XUnitVersion>
+    <BogusVersion>22.1.2</BogusVersion>
+    <MoqVersion>4.8.3</MoqVersion>
   </PropertyGroup>
 
 </Project>
diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj
index 1e8b227f3c..21de8e1aa2 100644
--- a/benchmarks/Benchmarks.csproj
+++ b/benchmarks/Benchmarks.csproj
@@ -5,7 +5,7 @@
     <AssemblyName>Benchmarks</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
-    <PackageReference Include="BenchmarkDotNet" Version="0.10.10" />
+    <PackageReference Include="BenchmarkDotNet" Version="0.10.14" />
     <PackageReference Include="moq" Version="$(MoqVersion)" />
     <PackageReference Include="xunit" Version="$(xUnitVersion)" />
   </ItemGroup>
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs
index c86425b00c..c9788bf82f 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs
@@ -1,4 +1,4 @@
-// <auto-generated />
+// <auto-generated />
 using JsonApiDotNetCoreExample.Data;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -7,6 +7,7 @@
 using Microsoft.EntityFrameworkCore.Storage;
 using Microsoft.EntityFrameworkCore.Storage.Internal;
 using System;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
 
 namespace JsonApiDotNetCoreExample.Migrations
 {
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
index ba19b62ef6..cc696f54bf 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
@@ -1,7 +1,8 @@
-using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Metadata;
 using Microsoft.EntityFrameworkCore.Migrations;
 using System;
 using System.Collections.Generic;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
 
 namespace JsonApiDotNetCoreExample.Migrations
 {
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs
index c0794103fe..08c284393e 100755
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs
@@ -1,4 +1,4 @@
-// <auto-generated />
+// <auto-generated />
 using JsonApiDotNetCoreExample.Data;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -7,6 +7,7 @@
 using Microsoft.EntityFrameworkCore.Storage;
 using Microsoft.EntityFrameworkCore.Storage.Internal;
 using System;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
 
 namespace JsonApiDotNetCoreExample.Migrations
 {
diff --git a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
index eed5f1b09e..efdaa68e5b 100755
--- a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
+++ b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj
@@ -18,7 +18,7 @@
     <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftLoggingVersion)" />
     <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
     <PackageReference Include="Npgsql" Version="$(NpgsqlVersion)" />
-    <PackageReference Include="Dapper" Version="1.50.2" />
+    <PackageReference Include="Dapper" Version="1.50.5" />
   </ItemGroup>
 
 </Project>
diff --git a/src/Examples/ReportsExample/ReportsExample.csproj b/src/Examples/ReportsExample/ReportsExample.csproj
index 48df3ea2c8..24c01b9a8d 100644
--- a/src/Examples/ReportsExample/ReportsExample.csproj
+++ b/src/Examples/ReportsExample/ReportsExample.csproj
@@ -17,7 +17,7 @@
     <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftLoggingVersion)" />
     <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
     <PackageReference Include="Npgsql" Version="$(NpgsqlVersion)" />
-    <PackageReference Include="Dapper" Version="1.50.2" />
+    <PackageReference Include="Dapper" Version="1.50.5" />
   </ItemGroup>
 
 </Project>
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 960f0f84ea..b8af04e278 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -17,14 +17,14 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Ben.Demystifier" Version="0.1.0" />
+    <PackageReference Include="Ben.Demystifier" Version="0.1.1" />
     <PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
     <PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftLoggingVersion)" />
-    <PackageReference Include="System.Memory" Version="4.5.0-preview2-26406-04" />
-    <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
     <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
+    <PackageReference Include="System.Memory" Version="4.5.0" />
+    <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
   </ItemGroup>
 
   <!-- 
diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
index b1df354bf7..86e6aca246 100755
--- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
@@ -19,13 +19,13 @@
   <ItemGroup>
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="$(AspNetCoreVersion)" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitVersion)" />
     <PackageReference Include="xunit" Version="$(XUnitVersion)" />
     <PackageReference Include="Bogus" Version="$(BogusVersion)" />
     <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
     <PackageReference Include="Moq" Version="$(MoqVersion)" />
   </ItemGroup>
-  
+
   <ItemGroup>
     <DotNetCliToolReference Include="dotnet-xunit" Version="$(XUnitVersion)" />
     <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="1.0.0" />
diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
index f1d4044e0b..28aad1dbf8 100644
--- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
+++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
@@ -21,7 +21,7 @@
   </ItemGroup>
   <ItemGroup>
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitVersion)" />
     <PackageReference Include="xunit" Version="$(XUnitVersion)" />
     <PackageReference Include="Bogus" Version="$(BogusVersion)" />
     <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
diff --git a/test/OperationsExampleTests/OperationsExampleTests.csproj b/test/OperationsExampleTests/OperationsExampleTests.csproj
index 13f68faf5a..30e5604073 100644
--- a/test/OperationsExampleTests/OperationsExampleTests.csproj
+++ b/test/OperationsExampleTests/OperationsExampleTests.csproj
@@ -10,7 +10,7 @@
     <PackageReference Include="moq" Version="$(MoqVersion)" />
     <PackageReference Include="xunit" Version="$(XUnitVersion)" />
     <PackageReference Include="Bogus" Version="$(BogusVersion)" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitVersion)" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\src\Examples\OperationsExample\OperationsExample.csproj" />
diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj
index a6ed346e7d..a89be46ecd 100644
--- a/test/UnitTests/UnitTests.csproj
+++ b/test/UnitTests/UnitTests.csproj
@@ -9,7 +9,7 @@
   </ItemGroup>
   <ItemGroup>
   <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitVersion)" />
     <PackageReference Include="xunit" Version="$(XUnitVersion)" />
     <PackageReference Include="Moq" Version="$(MoqVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.2" />

From a970745efa2ac292b2d4885ceb27f5e477cf5aa7 Mon Sep 17 00:00:00 2001
From: Bj <btecu@outlook.com>
Date: Mon, 11 Jun 2018 23:26:10 -0400
Subject: [PATCH 183/227] Fix tests, cleanup warning (deprecations)

---
 .../Controllers/TodoItemsCustomController.cs  |  5 -----
 .../Controllers/JsonApiControllerMixin.cs     | 20 ++++++++-----------
 .../Extensibility/CustomErrorTests.cs         |  4 ++--
 .../Acceptance/Spec/AttributeFilterTests.cs   |  8 ++++----
 .../Acceptance/Spec/DocumentTests/Included.cs |  6 +++---
 .../Spec/DocumentTests/PagingTests.cs         | 19 +++---------------
 .../Acceptance/Spec/QueryParameters.cs        |  2 +-
 test/OperationsExampleTests/Add/AddTests.cs   |  2 +-
 .../Get/GetByIdTests.cs                       | 14 ++++++-------
 .../Get/GetRelationshipTests.cs               |  2 +-
 test/OperationsExampleTests/Get/GetTests.cs   |  2 +-
 .../Transactions/TransactionFailureTests.cs   |  2 +-
 .../Update/UpdateTests.cs                     |  2 +-
 .../Builders/DocumentBuilder_Tests.cs         |  4 ++--
 .../JsonApiControllerMixin_Tests.cs           | 20 +++++++++----------
 .../Internal/ContextGraphBuilder_Tests.cs     |  2 +-
 .../Serialization/JsonApiDeSerializerTests.cs |  2 +-
 17 files changed, 47 insertions(+), 69 deletions(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs
index fc25f8396e..f5f3e111d9 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs
@@ -39,11 +39,6 @@ public class CustomJsonApiController<T, TId>
         private readonly IResourceService<T, TId> _resourceService;
         private readonly IJsonApiContext _jsonApiContext;
 
-        protected IActionResult UnprocessableEntity()
-        {
-            return new StatusCodeResult(422);
-        }
-
         protected IActionResult Forbidden()
         {
             return new StatusCodeResult(403);
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
index 840422eb6c..8c3099dde1 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs
@@ -7,11 +7,6 @@ namespace JsonApiDotNetCore.Controllers
 {
     public abstract class JsonApiControllerMixin : ControllerBase
     {
-        protected IActionResult UnprocessableEntity()
-        {
-            return new StatusCodeResult(422);
-        }
-
         protected IActionResult Forbidden()
         {
             return new StatusCodeResult(403);
@@ -23,18 +18,19 @@ protected IActionResult Error(Error error)
             {
                 Errors = new List<Error> { error }
             };
-            var result = new ObjectResult(errorCollection);
-            result.StatusCode = error.StatusCode;
 
-            return result;
+            return new ObjectResult(errorCollection)
+            {
+                StatusCode = error.StatusCode
+            };
         }
 
         protected IActionResult Errors(ErrorCollection errors)
         {
-            var result = new ObjectResult(errors);
-            result.StatusCode = GetErrorStatusCode(errors);
-
-            return result;
+            return new ObjectResult(errors)
+            {
+                StatusCode = GetErrorStatusCode(errors)
+            };
         }
 
         private int GetErrorStatusCode(ErrorCollection errors)
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomErrorTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomErrorTests.cs
index ce2b541f5b..fcc6e5ffde 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomErrorTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomErrorTests.cs
@@ -11,7 +11,7 @@ public class CustomErrorTests
         public void Can_Return_Custom_Error_Types()
         {
             // arrange
-            var error = new CustomError("507", "title", "detail", "custom");
+            var error = new CustomError(507, "title", "detail", "custom");
             var errorCollection = new ErrorCollection();
             errorCollection.Add(error);
 
@@ -36,7 +36,7 @@ public void Can_Return_Custom_Error_Types()
         }
 
         class CustomError : Error {
-            public CustomError(string status, string title, string detail, string myProp)
+            public CustomError(int status, string title, string detail, string myProp)
             : base(status, title, detail)
             {
                 MyCustomProperty = myProp;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index 428e3cadf3..b928df4ada 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -131,7 +131,7 @@ public async Task Can_Filter_On_Not_Equal_Values()
 
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-            Assert.False(deserializedTodoItems.Any(i => i.Ordinal == todoItem.Ordinal));
+            Assert.DoesNotContain(deserializedTodoItems, x => x.Ordinal == todoItem.Ordinal);
         }
 
         [Fact]
@@ -170,8 +170,8 @@ public async Task Can_Filter_On_In_Array_Values()
             Assert.Equal(guids.Count(), deserializedTodoItems.Count());
             foreach (var item in deserializedTodoItems)
             {
-                Assert.True(guids.Contains(item.GuidProperty));
-                Assert.False(notInGuids.Contains(item.GuidProperty));
+                Assert.Contains(item.GuidProperty, guids);
+                Assert.DoesNotContain(item.GuidProperty, notInGuids);
             }
         }
 
@@ -207,7 +207,7 @@ public async Task Can_Filter_On_Related_In_Array_Values()
             Assert.NotNull(included);
             Assert.NotEmpty(included);
             foreach (var item in included)
-                Assert.True(ownerFirstNames.Contains(item.Attributes["first-name"]));
+                Assert.Contains(item.Attributes["first-name"], ownerFirstNames);
 
         }
     }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
index 343526f7d8..25f81fb66c 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
@@ -174,7 +174,7 @@ public async Task GET_Included_DoesNot_Duplicate_Records_ForMultipleRelationship
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotEmpty(documents.Included);
-            Assert.Equal(1, documents.Included.Count);
+            Assert.Single(documents.Included);
         }
 
         [Fact]
@@ -209,7 +209,7 @@ public async Task GET_Included_DoesNot_Duplicate_Records_If_HasOne_Exists_Twice(
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotEmpty(documents.Included);
-            Assert.Equal(1, documents.Included.Count);
+            Assert.Single(documents.Included);
         }
 
         [Fact]
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
index faae94a3d8..e50032fce1 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs
@@ -1,4 +1,4 @@
-using System.Net;
+using System.Net;
 using System.Net.Http;
 using System.Threading.Tasks;
 using JsonApiDotNetCoreExample;
@@ -6,7 +6,6 @@
 using Microsoft.AspNetCore.TestHost;
 using Newtonsoft.Json;
 using Xunit;
-using Person = JsonApiDotNetCoreExample.Models.Person;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCoreExample.Data;
 using Bogus;
@@ -18,28 +17,16 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests
     [Collection("WebHostCollection")]
     public class PagingTests
     {
-        private TestFixture<TestStartup> _fixture;
-        private AppDbContext _context;
-        private Faker<Person> _personFaker;
-        private Faker<TodoItem> _todoItemFaker;
-        private Faker<TodoItemCollection> _todoItemCollectionFaker;
-        private DateTime CurrentTime;
+        private readonly AppDbContext _context;
+        private readonly Faker<TodoItem> _todoItemFaker;
 
         public PagingTests(TestFixture<TestStartup> fixture)
         {
-            _fixture = fixture;
             _context = fixture.GetService<AppDbContext>();
-            _personFaker = new Faker<Person>()
-                .RuleFor(p => p.FirstName, f => f.Name.FirstName())
-                .RuleFor(p => p.LastName, f => f.Name.LastName());
-
             _todoItemFaker = new Faker<TodoItem>()
                 .RuleFor(t => t.Description, f => f.Lorem.Sentence())
                 .RuleFor(t => t.Ordinal, f => f.Random.Number())
                 .RuleFor(t => t.CreatedDate, f => f.Date.Past());
-
-            _todoItemCollectionFaker = new Faker<TodoItemCollection>()
-                .RuleFor(t => t.Name, f => f.Company.CatchPhrase());
         }
 
         [Fact]
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs
index f5f61e156d..58b2323da5 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs
@@ -39,7 +39,7 @@ public async Task Server_Returns_400_ForUnknownQueryParam()
 
             // assert
             Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
-            Assert.Equal(1, body.Errors.Count);
+            Assert.Single(body.Errors);
             Assert.Equal($"[{queryKey}, {queryValue}] is not a valid query.", body.Errors[0].Title);
         }
     }
diff --git a/test/OperationsExampleTests/Add/AddTests.cs b/test/OperationsExampleTests/Add/AddTests.cs
index 39e9e8a2a6..47aba439d6 100644
--- a/test/OperationsExampleTests/Add/AddTests.cs
+++ b/test/OperationsExampleTests/Add/AddTests.cs
@@ -156,7 +156,7 @@ public async Task Can_Create_Author_With_Article()
             Assert.Equal(author.Name, lastAuthor.Name);
 
             // article validation
-            Assert.Equal(1, lastAuthor.Articles.Count);
+            Assert.Single(lastAuthor.Articles);
             Assert.Equal(article.Name, lastAuthor.Articles[0].Name);
             Assert.Equal(articleOperationResult.DataObject.Id, lastAuthor.Articles[0].StringId);
         }
diff --git a/test/OperationsExampleTests/Get/GetByIdTests.cs b/test/OperationsExampleTests/Get/GetByIdTests.cs
index 1dee2867ce..1056082895 100644
--- a/test/OperationsExampleTests/Get/GetByIdTests.cs
+++ b/test/OperationsExampleTests/Get/GetByIdTests.cs
@@ -36,14 +36,14 @@ public async Task Can_Get_Author_By_Id()
             };
 
             // act
-            var result = await PatchAsync<OperationsDocument>("api/bulk", content);
+            var (response, data) = await PatchAsync<OperationsDocument>("api/bulk", content);
 
             // assert
-            Assert.NotNull(result.response);
-            Assert.NotNull(result.data);
-            Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(1, result.data.Operations.Count);
-            Assert.Equal(author.Id.ToString(), result.data.Operations.Single().DataObject.Id);
+            Assert.NotNull(response);
+            Assert.NotNull(data);
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Single(data.Operations);
+            Assert.Equal(author.Id.ToString(), data.Operations.Single().DataObject.Id);
         }
 
         [Fact]
@@ -69,7 +69,7 @@ public async Task Get_Author_By_Id_Returns_404_If_NotFound()
             Assert.NotNull(response);
             Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
             Assert.NotNull(data);
-            Assert.Equal(1, data.Errors.Count);
+            Assert.Single(data.Errors);
             Assert.True(data.Errors[0].Detail.Contains("authors"), "The error detail should contain the name of the entity that could not be found.");
             Assert.True(data.Errors[0].Detail.Contains(authorId), "The error detail should contain the entity id that could not be found");
             Assert.True(data.Errors[0].Title.Contains("operation[0]"), "The error title should contain the operation identifier that failed");
diff --git a/test/OperationsExampleTests/Get/GetRelationshipTests.cs b/test/OperationsExampleTests/Get/GetRelationshipTests.cs
index 03f276da17..8599e92a1e 100644
--- a/test/OperationsExampleTests/Get/GetRelationshipTests.cs
+++ b/test/OperationsExampleTests/Get/GetRelationshipTests.cs
@@ -43,7 +43,7 @@ public async Task Can_Get_Article_Author()
             Assert.NotNull(response);
             Assert.NotNull(data);
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-            Assert.Equal(1, data.Operations.Count);
+            Assert.Single(data.Operations);
             var resourceObject = data.Operations.Single().DataObject;
             Assert.Equal(author.Id.ToString(), resourceObject.Id);
             Assert.Equal("authors", resourceObject.Type);
diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs
index bf1c15e3a4..78e7eeb976 100644
--- a/test/OperationsExampleTests/Get/GetTests.cs
+++ b/test/OperationsExampleTests/Get/GetTests.cs
@@ -44,7 +44,7 @@ public async Task Can_Get_Authors()
             Assert.NotNull(result.response);
             Assert.NotNull(result.data);
             Assert.Equal(HttpStatusCode.OK, result.response.StatusCode);
-            Assert.Equal(1, result.data.Operations.Count);
+            Assert.Single(result.data.Operations);
             Assert.Equal(expectedCount, result.data.Operations.Single().DataList.Count);
         }
     }
diff --git a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
index 05dea7f29d..191711651d 100644
--- a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
+++ b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs
@@ -68,7 +68,7 @@ public async Task Cannot_Create_Author_If_Article_Creation_Fails()
             // for now, it is up to application implementations to perform validation and 
             // provide the proper HTTP response code
             Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
-            Assert.Equal(1, data.Errors.Count);
+            Assert.Single(data.Errors);
             Assert.Contains("operation[1] (add)", data.Errors[0].Title);
 
             var dbAuthors = await context.Authors.Where(a => a.Name == author.Name).ToListAsync();
diff --git a/test/OperationsExampleTests/Update/UpdateTests.cs b/test/OperationsExampleTests/Update/UpdateTests.cs
index c5d0f20900..c5d220b2f5 100644
--- a/test/OperationsExampleTests/Update/UpdateTests.cs
+++ b/test/OperationsExampleTests/Update/UpdateTests.cs
@@ -52,7 +52,7 @@ public async Task Can_Update_Author()
             Assert.NotNull(response);
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotNull(data);
-            Assert.Equal(1, data.Operations.Count);
+            Assert.Single(data.Operations);
 
             var attrs = data.Operations.Single().DataObject.Attributes;
             Assert.Equal(updates.Name, attrs["name"]);
diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index fc816765eb..84c1f3f5c7 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -190,7 +190,7 @@ public void Build_Can_Build_Arrays()
 
             var documents = documentBuilder.Build(entities);
 
-            Assert.Equal(1, documents.Data.Count);
+            Assert.Single(documents.Data);
         }
 
         [Fact]
@@ -201,7 +201,7 @@ public void Build_Can_Build_CustomIEnumerables()
 
             var documents = documentBuilder.Build(entities);
 
-            Assert.Equal(1, documents.Data.Count);
+            Assert.Single(documents.Data);
         }
 
 
diff --git a/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs b/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs
index a18aeaf668..c7a4a6cb4d 100644
--- a/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs
+++ b/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs
@@ -16,26 +16,26 @@ public void Errors_Correctly_Infers_Status_Code()
             // arrange
             var errors422 = new ErrorCollection {
                 Errors = new List<Error> {
-                    new Error("422", "bad specific"),
-                    new Error("422", "bad other specific"),
+                    new Error(422, "bad specific"),
+                    new Error(422, "bad other specific"),
                 }
             };
 
             var errors400 = new ErrorCollection {
                 Errors = new List<Error> {
-                    new Error("200", "weird"),
-                    new Error("400", "bad"),
-                    new Error("422", "bad specific"),
+                    new Error(200, "weird"),
+                    new Error(400, "bad"),
+                    new Error(422, "bad specific"),
                 }
             };
 
             var errors500 = new ErrorCollection {
                 Errors = new List<Error> {
-                    new Error("200", "weird"),
-                    new Error("400", "bad"),
-                    new Error("422", "bad specific"),
-                    new Error("500", "really bad"),
-                    new Error("502", "really bad specific"),
+                    new Error(200, "weird"),
+                    new Error(400, "bad"),
+                    new Error(422, "bad specific"),
+                    new Error(500, "really bad"),
+                    new Error(502, "really bad specific"),
                 }
             };
             
diff --git a/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs b/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs
index ce8316b89d..5f56ac0bd8 100644
--- a/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs
+++ b/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs
@@ -33,7 +33,7 @@ public void Adding_DbContext_Members_That_DoNot_Implement_IIdentifiable_Creates_
             var contextGraph = contextGraphBuilder.Build() as ContextGraph;
 
             // assert
-            Assert.Equal(1, contextGraph.ValidationResults.Count);
+            Assert.Single(contextGraph.ValidationResults);
             Assert.Contains(contextGraph.ValidationResults, v => v.LogLevel == LogLevel.Warning);
         }
 
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index ec34d87d24..be16d1d9d7 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -181,7 +181,7 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate()
 
             // assert
             Assert.NotNull(result.ComplexMember);
-            Assert.Equal(1, attributesToUpdate.Count);
+            Assert.Single(attributesToUpdate);
 
             foreach (var attr in attributesToUpdate)
                 Assert.False(attr.Key.IsImmutable);

From a460d99b4d897b9511ff0846f2bfc01fb05a7c9a Mon Sep 17 00:00:00 2001
From: Bj <btecu@outlook.com>
Date: Wed, 13 Jun 2018 17:22:22 -0400
Subject: [PATCH 184/227] Reduce verbosity

---
 src/Examples/JsonApiDotNetCoreExample/appsettings.json | 6 +++---
 src/Examples/OperationsExample/appsettings.json        | 6 +++---
 test/OperationsExampleTests/appsettings.json           | 6 +++---
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/appsettings.json b/src/Examples/JsonApiDotNetCoreExample/appsettings.json
index 578225ef14..c468439079 100755
--- a/src/Examples/JsonApiDotNetCoreExample/appsettings.json
+++ b/src/Examples/JsonApiDotNetCoreExample/appsettings.json
@@ -5,9 +5,9 @@
     "Logging": {
         "IncludeScopes": false,
         "LogLevel": {
-            "Default": "Trace",
-            "System": "Trace",
-            "Microsoft": "Trace"
+            "Default": "Warning",
+            "System": "Warning",
+            "Microsoft": "Warning"
         }
     }
 }
diff --git a/src/Examples/OperationsExample/appsettings.json b/src/Examples/OperationsExample/appsettings.json
index 0d77cd40f2..73030b1743 100644
--- a/src/Examples/OperationsExample/appsettings.json
+++ b/src/Examples/OperationsExample/appsettings.json
@@ -5,9 +5,9 @@
     "Logging": {
         "IncludeScopes": false,
         "LogLevel": {
-            "Default": "Trace",
-            "System": "Trace",
-            "Microsoft": "Trace"
+            "Default": "Warning",
+            "System": "Warning",
+            "Microsoft": "Warning"
         }
     }
 }
diff --git a/test/OperationsExampleTests/appsettings.json b/test/OperationsExampleTests/appsettings.json
index 0d77cd40f2..73030b1743 100644
--- a/test/OperationsExampleTests/appsettings.json
+++ b/test/OperationsExampleTests/appsettings.json
@@ -5,9 +5,9 @@
     "Logging": {
         "IncludeScopes": false,
         "LogLevel": {
-            "Default": "Trace",
-            "System": "Trace",
-            "Microsoft": "Trace"
+            "Default": "Warning",
+            "System": "Warning",
+            "Microsoft": "Warning"
         }
     }
 }

From d45b1976283c18a6b5b2ef871a8a8daa9d19dab6 Mon Sep 17 00:00:00 2001
From: Bj <btecu@outlook.com>
Date: Wed, 13 Jun 2018 17:35:05 -0400
Subject: [PATCH 185/227] Further reduce tests verbosity

---
 src/Examples/JsonApiDotNetCoreExample/Startup.cs    |  3 +--
 src/Examples/NoEntityFrameworkExample/Startup.cs    |  3 +--
 src/Examples/OperationsExample/Startup.cs           |  3 +--
 src/Examples/ReportsExample/appsettings.json        |  2 +-
 .../Serialization/JsonApiSerializer.cs              |  6 +++++-
 .../Services/EntityResourceService.cs               | 11 ++++++++---
 src/JsonApiDotNetCore/Services/QueryAccessor.cs     | 13 +++++++++++--
 .../Helpers/Startups/MetaStartup.cs                 |  2 +-
 test/JsonApiDotNetCoreExampleTests/appsettings.json |  6 +++---
 test/NoEntityFrameworkTests/appsettings.json        |  6 +++---
 10 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/Startup.cs b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
index 378a948a61..2c7574e1a2 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Startup.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
@@ -28,7 +28,7 @@ public Startup(IHostingEnvironment env)
         public virtual IServiceProvider ConfigureServices(IServiceCollection services)
         {
             var loggerFactory = new LoggerFactory();
-            loggerFactory.AddConsole(LogLevel.Trace);
+            loggerFactory.AddConsole(LogLevel.Warning);
 
             services
                 .AddSingleton<ILoggerFactory>(loggerFactory)
@@ -57,7 +57,6 @@ public virtual void Configure(
             context.Database.EnsureCreated();
 
             loggerFactory.AddConsole(Config.GetSection("Logging"));
-            loggerFactory.AddDebug();
 
             app.UseJsonApi();
         }
diff --git a/src/Examples/NoEntityFrameworkExample/Startup.cs b/src/Examples/NoEntityFrameworkExample/Startup.cs
index dfba27ddd9..b1f1d05188 100755
--- a/src/Examples/NoEntityFrameworkExample/Startup.cs
+++ b/src/Examples/NoEntityFrameworkExample/Startup.cs
@@ -1,4 +1,4 @@
-using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Services;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
@@ -55,7 +55,6 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
         public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, AppDbContext context)
         {
             loggerFactory.AddConsole(Configuration.GetSection("Logging"));
-            loggerFactory.AddDebug();
 
             context.Database.EnsureCreated();
 
diff --git a/src/Examples/OperationsExample/Startup.cs b/src/Examples/OperationsExample/Startup.cs
index c11a3e9d26..a889ad85d6 100644
--- a/src/Examples/OperationsExample/Startup.cs
+++ b/src/Examples/OperationsExample/Startup.cs
@@ -27,7 +27,7 @@ public Startup(IHostingEnvironment env)
         public virtual IServiceProvider ConfigureServices(IServiceCollection services)
         {
             var loggerFactory = new LoggerFactory();
-            loggerFactory.AddConsole(LogLevel.Trace);
+            loggerFactory.AddConsole(LogLevel.Warning);
 
             services.AddSingleton<ILoggerFactory>(loggerFactory);
 
@@ -47,7 +47,6 @@ public virtual void Configure(
             context.Database.EnsureCreated();
 
             loggerFactory.AddConsole(Config.GetSection("Logging"));
-            loggerFactory.AddDebug();
             app.UseJsonApi();
         }
 
diff --git a/src/Examples/ReportsExample/appsettings.json b/src/Examples/ReportsExample/appsettings.json
index 125f7a4ae9..5766595e6d 100644
--- a/src/Examples/ReportsExample/appsettings.json
+++ b/src/Examples/ReportsExample/appsettings.json
@@ -2,7 +2,7 @@
   "Logging": {
     "IncludeScopes": false,
     "LogLevel": {
-      "Default": "Information"
+      "Default": "Warning"
     }
   }
 }
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
index 20d119ff07..500101cc62 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
@@ -65,7 +65,11 @@ private string GetErrorJson(object responseObject, ILogger logger)
             }
             else
             {
-                logger?.LogInformation("Response was not a JSONAPI entity. Serializing as plain JSON.");
+                if (logger?.IsEnabled(LogLevel.Information) == true)
+                {
+                    logger.LogInformation("Response was not a JSONAPI entity. Serializing as plain JSON.");
+                }
+                
                 return JsonConvert.SerializeObject(responseObject);
             }
         }
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index 642ee00a57..a3094eb8f9 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -89,8 +89,10 @@ public virtual async Task<object> GetRelationshipAsync(TId id, string relationsh
 
             if (relationshipName == null)
                 throw new JsonApiException(422, "Relationship name not specified.");
-
-            _logger.LogTrace($"Looking up '{relationshipName}'...");
+            if (_logger.IsEnabled(LogLevel.Trace))
+            {
+                _logger.LogTrace($"Looking up '{relationshipName}'...");
+            }
 
             var entity = await _entities.GetAndIncludeAsync(id, relationshipName);
             // TODO: it would be better if we could distinguish whether or not the relationship was not found,
@@ -166,7 +168,10 @@ protected virtual async Task<IEnumerable<T>> ApplyPageQueryAsync(IQueryable<T> e
             if (!pageManager.IsPaginated)
                 return await _entities.ToListAsync(entities);
 
-            _logger?.LogInformation($"Applying paging query. Fetching page {pageManager.CurrentPage} with {pageManager.PageSize} entities");
+            if (_logger?.IsEnabled(LogLevel.Information) == true)
+            {
+                _logger?.LogInformation($"Applying paging query. Fetching page {pageManager.CurrentPage} with {pageManager.PageSize} entities");
+            }
 
             return await _entities.PageAsync(entities, pageManager.PageSize, pageManager.CurrentPage);
         }
diff --git a/src/JsonApiDotNetCore/Services/QueryAccessor.cs b/src/JsonApiDotNetCore/Services/QueryAccessor.cs
index 41bc64151b..dc9ff7ef0a 100644
--- a/src/JsonApiDotNetCore/Services/QueryAccessor.cs
+++ b/src/JsonApiDotNetCore/Services/QueryAccessor.cs
@@ -45,7 +45,11 @@ public bool TryGetValue<T>(string key, out T value)
             var stringValue = GetFilterValue(key);
             if (stringValue == null)
             {
-                _logger.LogInformation($"'{key}' was not found in the query collection");
+                if (_logger.IsEnabled(LogLevel.Information))
+                {
+                    _logger.LogInformation($"'{key}' was not found in the query collection");
+                }
+
                 return false;
             }
 
@@ -56,7 +60,12 @@ public bool TryGetValue<T>(string key, out T value)
             }
             catch (FormatException)
             {
-                _logger.LogInformation($"'{value}' is not a valid '{typeof(T).Name}' value for query parameter {key}");
+                if (_logger.IsEnabled(LogLevel.Information))
+                {
+                    _logger.LogInformation(
+                        $"'{value}' is not a valid '{typeof(T).Name}' value for query parameter {key}");
+                }
+
                 return false;
             }
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/MetaStartup.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/MetaStartup.cs
index df32a1223a..6bc5a08016 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/MetaStartup.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/MetaStartup.cs
@@ -20,7 +20,7 @@ public MetaStartup(IHostingEnvironment env)
         public override IServiceProvider ConfigureServices(IServiceCollection services)
         {
             var loggerFactory = new LoggerFactory();
-            loggerFactory.AddConsole(LogLevel.Trace);
+            loggerFactory.AddConsole(LogLevel.Warning);
 
             services
                 .AddSingleton<ILoggerFactory>(loggerFactory)
diff --git a/test/JsonApiDotNetCoreExampleTests/appsettings.json b/test/JsonApiDotNetCoreExampleTests/appsettings.json
index e65cee8d0d..c468439079 100644
--- a/test/JsonApiDotNetCoreExampleTests/appsettings.json
+++ b/test/JsonApiDotNetCoreExampleTests/appsettings.json
@@ -5,9 +5,9 @@
     "Logging": {
         "IncludeScopes": false,
         "LogLevel": {
-            "Default": "Error",
-            "System": "Information",
-            "Microsoft": "Information"
+            "Default": "Warning",
+            "System": "Warning",
+            "Microsoft": "Warning"
         }
     }
 }
diff --git a/test/NoEntityFrameworkTests/appsettings.json b/test/NoEntityFrameworkTests/appsettings.json
index 01f85e6699..c468439079 100644
--- a/test/NoEntityFrameworkTests/appsettings.json
+++ b/test/NoEntityFrameworkTests/appsettings.json
@@ -5,9 +5,9 @@
     "Logging": {
         "IncludeScopes": false,
         "LogLevel": {
-            "Default": "Debug",
-            "System": "Information",
-            "Microsoft": "Information"
+            "Default": "Warning",
+            "System": "Warning",
+            "Microsoft": "Warning"
         }
     }
 }

From 9441893ede9833fbdc886149b9b1776dd6af42dd Mon Sep 17 00:00:00 2001
From: Bj <btecu@outlook.com>
Date: Wed, 13 Jun 2018 17:57:47 -0400
Subject: [PATCH 186/227] Make paths consistent

---
 benchmarks/Benchmarks.csproj                                  | 2 +-
 src/Examples/OperationsExample/OperationsExample.csproj       | 2 +-
 .../JsonApiDotNetCoreExampleTests.csproj                      | 2 +-
 test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj     | 2 +-
 test/OperationsExampleTests/OperationsExampleTests.csproj     | 4 ++--
 test/UnitTests/UnitTests.csproj                               | 4 ++--
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj
index 1e8b227f3c..9f3320575b 100644
--- a/benchmarks/Benchmarks.csproj
+++ b/benchmarks/Benchmarks.csproj
@@ -10,6 +10,6 @@
     <PackageReference Include="xunit" Version="$(xUnitVersion)" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\src\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
+    <ProjectReference Include="../src/JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
   </ItemGroup>
 </Project>
diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj
index 69ad5653ce..bae7f3063f 100644
--- a/src/Examples/OperationsExample/OperationsExample.csproj
+++ b/src/Examples/OperationsExample/OperationsExample.csproj
@@ -8,7 +8,7 @@
 
   <ItemGroup>
     <ProjectReference Include="../../JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
-    <ProjectReference Include="..\JsonApiDotNetCoreExample\JsonApiDotNetCoreExample.csproj" />
+    <ProjectReference Include="../JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
index b1df354bf7..34bc61b657 100755
--- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
@@ -13,7 +13,7 @@
   <ItemGroup>
     <ProjectReference Include="../../src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj" />
     <ProjectReference Include="../../src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj" />
-    <ProjectReference Include="..\UnitTests\UnitTests.csproj" />
+    <ProjectReference Include="../UnitTests/UnitTests.csproj" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
index f1d4044e0b..19b8cc61d2 100644
--- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
+++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj
@@ -17,7 +17,7 @@
     <ProjectReference Include="../../src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj" />
     <ProjectReference Include="../../test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj" />
     <ProjectReference Include="../../src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj" />
-    <ProjectReference Include="..\UnitTests\UnitTests.csproj" />
+    <ProjectReference Include="../UnitTests/UnitTests.csproj" />
   </ItemGroup>
   <ItemGroup>
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
diff --git a/test/OperationsExampleTests/OperationsExampleTests.csproj b/test/OperationsExampleTests/OperationsExampleTests.csproj
index 13f68faf5a..3b866d4207 100644
--- a/test/OperationsExampleTests/OperationsExampleTests.csproj
+++ b/test/OperationsExampleTests/OperationsExampleTests.csproj
@@ -13,8 +13,8 @@
     <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\src\Examples\OperationsExample\OperationsExample.csproj" />
-    <ProjectReference Include="..\UnitTests\UnitTests.csproj" />
+    <ProjectReference Include="../../src/Examples/OperationsExample/OperationsExample.csproj" />
+    <ProjectReference Include="../UnitTests/UnitTests.csproj" />
   </ItemGroup>
   <ItemGroup>
     <None Update="xunit.runner.json;appsettings.json">
diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj
index a6ed346e7d..39132d0b0a 100644
--- a/test/UnitTests/UnitTests.csproj
+++ b/test/UnitTests/UnitTests.csproj
@@ -4,8 +4,8 @@
     <IsPackable>false</IsPackable>
   </PropertyGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\src\JsonApiDotNetCore\JsonApiDotNetCore.csproj" />
-    <ProjectReference Include="..\..\src\Examples\JsonApiDotNetCoreExample\JsonApiDotNetCoreExample.csproj" />
+    <ProjectReference Include="../../src/JsonApiDotNetCore/JsonApiDotNetCore.csproj" />
+    <ProjectReference Include="../../src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj" />
   </ItemGroup>
   <ItemGroup>
   <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />

From d79b218dfb7bcb0adf5d758305ae58693c590ac6 Mon Sep 17 00:00:00 2001
From: Bj <btecu@outlook.com>
Date: Wed, 13 Jun 2018 17:58:03 -0400
Subject: [PATCH 187/227] Remove already included packages

---
 .../JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj | 5 -----
 src/Examples/OperationsExample/OperationsExample.csproj      | 5 -----
 .../JsonApiDotNetCoreExampleTests.csproj                     | 3 +--
 3 files changed, 1 insertion(+), 12 deletions(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
index 94e2a404a9..e588c81b4e 100755
--- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
+++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
@@ -25,9 +25,4 @@
     <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="$(EFCoreToolsVersion)" />
     <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
   </ItemGroup>
-
-  <ItemGroup>
-    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="$(EFCoreToolsVersion)" />
-  </ItemGroup>
-
 </Project>
diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj
index bae7f3063f..02eeabe976 100644
--- a/src/Examples/OperationsExample/OperationsExample.csproj
+++ b/src/Examples/OperationsExample/OperationsExample.csproj
@@ -26,9 +26,4 @@
     <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="$(EFCoreToolsVersion)" />
     <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
   </ItemGroup>
-
-  <ItemGroup>
-    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="$(EFCoreToolsVersion)" />
-  </ItemGroup>
-
 </Project>
diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
index 34bc61b657..53f1d4bf77 100755
--- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
+++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj
@@ -25,9 +25,8 @@
     <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
     <PackageReference Include="Moq" Version="$(MoqVersion)" />
   </ItemGroup>
-  
+
   <ItemGroup>
     <DotNetCliToolReference Include="dotnet-xunit" Version="$(XUnitVersion)" />
-    <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="1.0.0" />
   </ItemGroup>
 </Project>

From 7280ff7f14c5045ed80f9e4fc59cead7be11125b Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 13 Jun 2018 20:30:49 -0500
Subject: [PATCH 188/227] fix test issue and bump package version to 2.3.0

---
 .../JsonApiDotNetCoreExample.csproj           |  4 --
 .../OperationsExample.csproj                  |  4 --
 .../JsonApiDotNetCore.csproj                  |  2 +-
 .../Extensions/IQueryableExtensions.cs        | 41 ++++++++-----------
 .../Helpers/Extensions/StringExtensions.cs    |  6 +--
 5 files changed, 21 insertions(+), 36 deletions(-)

diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
index 94e2a404a9..fd657e83bf 100755
--- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
+++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj
@@ -26,8 +26,4 @@
     <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
   </ItemGroup>
 
-  <ItemGroup>
-    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="$(EFCoreToolsVersion)" />
-  </ItemGroup>
-
 </Project>
diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj
index 69ad5653ce..f44d8b35c8 100644
--- a/src/Examples/OperationsExample/OperationsExample.csproj
+++ b/src/Examples/OperationsExample/OperationsExample.csproj
@@ -27,8 +27,4 @@
     <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlPostgreSQLVersion)" />
   </ItemGroup>
 
-  <ItemGroup>
-    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="$(EFCoreToolsVersion)" />
-  </ItemGroup>
-
 </Project>
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index b8af04e278..e9d5eea415 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.2.5</VersionPrefix>
+    <VersionPrefix>2.3.0</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
index c774478227..a7bfb95b9d 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
@@ -12,38 +12,31 @@ namespace JsonApiDotNetCoreExampleTests.Helpers.Extensions
 {
     public static class IQueryableExtensions
     {
-        private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
-
-        private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler");
+        private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.Single(x => x.Name == "_queryCompiler");
 
-        private static readonly PropertyInfo NodeTypeProviderField = QueryCompilerTypeInfo.DeclaredProperties.Single(x => x.Name == "NodeTypeProvider");
+        private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
 
-        private static readonly MethodInfo CreateQueryParserMethod = QueryCompilerTypeInfo.DeclaredMethods.First(x => x.Name == "CreateQueryParser");
+        private static readonly FieldInfo QueryModelGeneratorField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_queryModelGenerator");
 
-        private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database");
+        private static readonly FieldInfo DatabaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database");
 
-        private static readonly PropertyInfo DatabaseDependenciesField
-            = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies");
+        private static readonly PropertyInfo DependenciesProperty = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies");
 
-        public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
+        public static string ToSql<TEntity>(this IQueryable<TEntity> queryable)
+            where TEntity : class
         {
-            if (!(query is EntityQueryable<TEntity>) && !(query is InternalDbSet<TEntity>))
-            {
-                throw new ArgumentException("Invalid query");
-            }
-
-            var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(query.Provider);
-            var nodeTypeProvider = (INodeTypeProvider)NodeTypeProviderField.GetValue(queryCompiler);
-            var parser = (IQueryParser)CreateQueryParserMethod.Invoke(queryCompiler, new object[] { nodeTypeProvider });
-            var queryModel = parser.GetParsedQuery(query.Expression);
-            var database = DataBaseField.GetValue(queryCompiler);
-            var queryCompilationContextFactory = ((DatabaseDependencies)DatabaseDependenciesField.GetValue(database)).QueryCompilationContextFactory;
+            if (!(queryable is EntityQueryable<TEntity>) && !(queryable is InternalDbSet<TEntity>))
+                throw new ArgumentException();
+
+            var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(queryable.Provider);
+            var queryModelGenerator = (IQueryModelGenerator)QueryModelGeneratorField.GetValue(queryCompiler);
+            var queryModel = queryModelGenerator.ParseQuery(queryable.Expression);
+            var database = DatabaseField.GetValue(queryCompiler);
+            var queryCompilationContextFactory = ((DatabaseDependencies)DependenciesProperty.GetValue(database)).QueryCompilationContextFactory;
             var queryCompilationContext = queryCompilationContextFactory.Create(false);
             var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();
             modelVisitor.CreateQueryExecutor<TEntity>(queryModel);
-            var sql = modelVisitor.Queries.First().ToString();
-
-            return sql;
+            return modelVisitor.Queries.Join(Environment.NewLine + Environment.NewLine);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/StringExtensions.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/StringExtensions.cs
index 19c7491d2a..dbe6b19feb 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/StringExtensions.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/StringExtensions.cs
@@ -2,14 +2,14 @@
 
 namespace JsonApiDotNetCoreExampleTests.Helpers.Extensions
 {
-
     public static class StringExtensions
     {
         public static string Normalize(this string input)
         {
             return Regex.Replace(input, @"\s+", string.Empty)
                 .ToUpper()
-                .Replace('"', '\'');
+                .Replace("\"", string.Empty)
+                .Replace("'", string.Empty);
         }
     }
-}
\ No newline at end of file
+}

From ca668fd43d4613a847ef0b6deb5644469c99e3b0 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Fri, 15 Jun 2018 14:21:31 -0500
Subject: [PATCH 189/227] Link to performance reports and related projects

---
 README.md | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 2250ef4568..81ebba79bf 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,14 @@ These are some steps you can take to help you understand what this project is an
 - [The json:api specification](http://jsonapi.org/format/)
 - [Demo [Video]](https://youtu.be/KAMuo6K7VcE)
 - [Our documentation](https://json-api-dotnet.github.io)
-- Check out the examples in the next section
+- [Check out the example projects](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples)
+
+## Related Projects
+
+- [Performance Reports](https://github.com/json-api-dotnet/PerformanceReports)
+- [JsonApiDotNetCore.MongoDb](https://github.com/json-api-dotnet/JsonApiDotNetCore.MongoDb)
+- [JsonApiDotNetCore.Marten](https://github.com/wayne-o/JsonApiDotNetCore.Marten)
+- [Todo List App](https://github.com/json-api-dotnet/TodoListExample)
 
 ## Examples
 

From 1847d7d5fa7bbb44f3bc4795802f1f4bd931a5eb Mon Sep 17 00:00:00 2001
From: Nathan Wise <nathanwise@gmail.com>
Date: Fri, 15 Jun 2018 15:36:15 -0400
Subject: [PATCH 190/227] Fixing issue where total-records was 0 on POST and
 PATCH calls.

---
 .../Services/JsonApiContext.cs                |   2 +
 .../Acceptance/Spec/DocumentTests/Meta.cs     | 114 ++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 0643d494d6..df71d3ab02 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -119,11 +119,13 @@ private PageManager GetPageManager()
                 return new PageManager();
 
             var query = QuerySet?.PageQuery ?? new PageQuery();
+            var requestMethod = _httpContextAccessor.HttpContext.Request.Method;
 
             return new PageManager
             {
                 DefaultPageSize = Options.DefaultPageSize,
                 CurrentPage = query.PageOffset,
+                TotalRecords = (requestMethod == "POST" || requestMethod == "PATCH") ? 1 : 0,
                 PageSize = query.PageSize > 0 ? query.PageSize : Options.DefaultPageSize
             };
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
index bb055e9935..013cd85bcb 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
@@ -1,6 +1,7 @@
 using System.Collections;
 using System.Net;
 using System.Net.Http;
+using System.Net.Http.Headers;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCoreExample;
@@ -54,6 +55,119 @@ public async Task Total_Record_Count_Included()
             Assert.Equal((long)expectedCount, (long)documents.Meta["total-records"]);
         }
 
+        [Fact]
+        public async Task Total_Record_Count_Not_Included_When_None()
+        {
+            // arrange
+            _context.TodoItems.RemoveRange(_context.TodoItems);
+            _context.SaveChanges();
+            var builder = new WebHostBuilder()
+                .UseStartup<MetaStartup>();
+
+            var httpMethod = new HttpMethod("GET");
+            var route = $"/api/v1/todo-items";
+
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // act
+            var response = await client.SendAsync(request);
+            var responseBody = await response.Content.ReadAsStringAsync();
+            var documents = JsonConvert.DeserializeObject<Documents>(responseBody);
+            
+            // assert
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Null(documents.Meta);
+        }
+
+        [Fact]
+        public async Task Total_Record_Count_Included_POST()
+        {
+            // arrange
+            _context.TodoItems.RemoveRange(_context.TodoItems);
+            _context.SaveChanges();
+            var expectedCount = 1;
+            var builder = new WebHostBuilder()
+                .UseStartup<MetaStartup>();
+
+            var httpMethod = new HttpMethod("POST");
+            var route = $"/api/v1/todo-items";
+
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+            var request = new HttpRequestMessage(httpMethod, route);
+            var content = new
+            {
+                data = new
+                {
+                    type = "todo-items",
+                    attributes = new
+                    {
+                        description = "New Description",
+                    }
+                }
+            };
+
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // act
+            var response = await client.SendAsync(request);
+            var responseBody = await response.Content.ReadAsStringAsync();
+            var documents = JsonConvert.DeserializeObject<Document>(responseBody);
+            
+            // assert
+            Assert.Equal(HttpStatusCode.Created, response.StatusCode);
+            Assert.NotNull(documents.Meta);
+            Assert.Equal((long)expectedCount, (long)documents.Meta["total-records"]);
+        }
+
+        [Fact]
+        public async Task Total_Record_Count_Included_PATCH()
+        {
+            // arrange
+            _context.TodoItems.RemoveRange(_context.TodoItems);
+            TodoItem todoItem = new TodoItem();
+            _context.TodoItems.Add(todoItem);
+            _context.SaveChanges();
+            var expectedCount = 1;
+            var builder = new WebHostBuilder()
+                .UseStartup<MetaStartup>();
+
+            var httpMethod = new HttpMethod("PATCH");
+            var route = $"/api/v1/todo-items/{todoItem.Id}";
+
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+            var request = new HttpRequestMessage(httpMethod, route);
+            var content = new
+            {
+                data = new
+                {
+                    type = "todo-items",
+                    id = todoItem.Id,
+                    attributes = new
+                    {
+                        description = "New Description",
+                    }
+                }
+            };
+
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // act
+            var response = await client.SendAsync(request);
+            var responseBody = await response.Content.ReadAsStringAsync();
+            var documents = JsonConvert.DeserializeObject<Document>(responseBody);
+            
+            // assert
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.NotNull(documents.Meta);
+            Assert.Equal((long)expectedCount, (long)documents.Meta["total-records"]);
+        }
+
         [Fact]
         public async Task EntityThatImplements_IHasMeta_Contains_MetaData()
         {

From 02d6510e8c4cc8f7184b62e39a0a16918e07f8bf Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Mon, 18 Jun 2018 11:34:44 -0500
Subject: [PATCH 191/227] make attr constructor public

unnecessary breaking change
---
 src/JsonApiDotNetCore/Models/AttrAttribute.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Models/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
index e38b47abec..f63d48ab70 100644
--- a/src/JsonApiDotNetCore/Models/AttrAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
@@ -33,7 +33,7 @@ public AttrAttribute(string publicName, bool isImmutable = false, bool isFiltera
             IsSortable = isSortable;
         }
 
-        internal AttrAttribute(string publicName, string internalName, bool isImmutable = false)
+        public AttrAttribute(string publicName, string internalName, bool isImmutable = false)
         {
             PublicAttributeName = publicName;
             InternalAttributeName = internalName;

From a3fc750058de8e45cebf06dc31bd8b28aee4e901 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Mon, 18 Jun 2018 11:35:50 -0500
Subject: [PATCH 192/227] update version 2.3.1

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index e9d5eea415..7019a8e6cc 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.3.0</VersionPrefix>
+    <VersionPrefix>2.3.1</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From a1e730bb3d36026009d8a457278e17a6a0087b93 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Mon, 18 Jun 2018 12:11:14 -0500
Subject: [PATCH 193/227] fix(IResourceService): should inherit from shorthand
 interfaces

---
 src/JsonApiDotNetCore/Services/Contract/IResourceService.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Services/Contract/IResourceService.cs b/src/JsonApiDotNetCore/Services/Contract/IResourceService.cs
index 82f3505c78..ec534a5f1b 100644
--- a/src/JsonApiDotNetCore/Services/Contract/IResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/IResourceService.cs
@@ -3,7 +3,7 @@
 namespace JsonApiDotNetCore.Services
 {
     public interface IResourceService<T> 
-        : IResourceService<T, int> 
+        : IResourceCmdService<T>, IResourceQueryService<T>, IResourceService<T, int> 
         where T : class, IIdentifiable<int>
     { }
 

From 0c474fa4c483ac2eb9de48ba3afe0dd42b144310 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Mon, 18 Jun 2018 12:13:14 -0500
Subject: [PATCH 194/227] fix(IResourceCmdService): inherit shorthand
 interfaces

---
 .../Services/Contract/IResourceCmdService.cs               | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Services/Contract/IResourceCmdService.cs b/src/JsonApiDotNetCore/Services/Contract/IResourceCmdService.cs
index 2633fd589b..0f6c5e64b7 100644
--- a/src/JsonApiDotNetCore/Services/Contract/IResourceCmdService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/IResourceCmdService.cs
@@ -2,7 +2,12 @@
 
 namespace JsonApiDotNetCore.Services
 {
-    public interface IResourceCmdService<T> : IResourceCmdService<T, int> 
+    public interface IResourceCmdService<T> : 
+        ICreateService<T>,
+        IUpdateService<T>,
+        IUpdateRelationshipService<T>,
+        IDeleteService<T>,
+        IResourceCmdService<T, int>
         where T : class, IIdentifiable<int>
     { }
 

From 32bef04453965d43db19a125f88d9fb8b4bb4589 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Mon, 18 Jun 2018 12:14:05 -0500
Subject: [PATCH 195/227] fix(IResourceQueryService): inherit shorthand
 interfaces

---
 .../Services/Contract/IResourceQueryService.cs             | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Services/Contract/IResourceQueryService.cs b/src/JsonApiDotNetCore/Services/Contract/IResourceQueryService.cs
index 8a9e247a3f..1cd4a94cf3 100644
--- a/src/JsonApiDotNetCore/Services/Contract/IResourceQueryService.cs
+++ b/src/JsonApiDotNetCore/Services/Contract/IResourceQueryService.cs
@@ -2,7 +2,12 @@
 
 namespace JsonApiDotNetCore.Services
 {
-    public interface IResourceQueryService<T> : IResourceQueryService<T, int> 
+    public interface IResourceQueryService<T> : 
+        IGetAllService<T>,
+        IGetByIdService<T>,
+        IGetRelationshipsService<T>,
+        IGetRelationshipService<T>,
+        IResourceQueryService<T, int>
         where T : class, IIdentifiable<int>
     { }
 

From 648c1814dc9bae899f75915a6aa37a7c7925b288 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Mon, 18 Jun 2018 12:17:35 -0500
Subject: [PATCH 196/227] bump version to 2.3.2

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 7019a8e6cc..75fc955402 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.3.1</VersionPrefix>
+    <VersionPrefix>2.3.2</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From d61bcbb68f09194501c034b804431523c02168e4 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 20 Jun 2018 18:37:54 -0500
Subject: [PATCH 197/227] PR feedback

---
 .../Builders/DocumentBuilder.cs               |  2 +-
 src/JsonApiDotNetCore/Internal/PageManager.cs |  4 +--
 .../JsonApiDotNetCore.csproj                  |  2 +-
 .../Services/JsonApiContext.cs                | 12 +++----
 .../Acceptance/Spec/DocumentTests/Meta.cs     | 35 +++++++++----------
 5 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 0beb0516c1..1a7a692101 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -75,7 +75,7 @@ private Dictionary<string, object> GetMeta(IIdentifiable entity)
             if (entity is IHasMeta metaEntity)
                 builder.Add(metaEntity.GetMeta(_jsonApiContext));
 
-            if (_jsonApiContext.Options.IncludeTotalRecordCount)
+            if (_jsonApiContext.Options.IncludeTotalRecordCount && _jsonApiContext.PageManager.TotalRecords != null)
                 builder.Add("total-records", _jsonApiContext.PageManager.TotalRecords);
 
             if (_requestMeta != null)
diff --git a/src/JsonApiDotNetCore/Internal/PageManager.cs b/src/JsonApiDotNetCore/Internal/PageManager.cs
index 17da00333a..1e35b71b4e 100644
--- a/src/JsonApiDotNetCore/Internal/PageManager.cs
+++ b/src/JsonApiDotNetCore/Internal/PageManager.cs
@@ -6,12 +6,12 @@ namespace JsonApiDotNetCore.Internal
 {
     public class PageManager
     {
-        public int TotalRecords { get; set; }
+        public int? TotalRecords { get; set; }
         public int PageSize { get; set; }
         public int DefaultPageSize { get; set; }
         public int CurrentPage { get; set; }
         public bool IsPaginated => PageSize > 0;
-        public int TotalPages => (TotalRecords == 0) ? -1 : (int)Math.Ceiling(decimal.Divide(TotalRecords, PageSize));
+        public int TotalPages => (TotalRecords == 0 || TotalRecords == null) ? -1 : (int)Math.Ceiling(decimal.Divide(TotalRecords.Value, PageSize));
 
         public RootLinks GetPageLinks(LinkBuilder linkBuilder)
         {
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index e9d5eea415..7019a8e6cc 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.3.0</VersionPrefix>
+    <VersionPrefix>2.3.1</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index df71d3ab02..21c4b56736 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -86,20 +86,20 @@ internal static bool PathIsRelationship(string requestPath)
             const char pathSegmentDelimiter = '/';
 
             var span = requestPath.AsSpan();
-            
+
             // we need to iterate over the string, from the end,
             // checking whether or not the 2nd to last path segment
             // is "relationships"
             // -2 is chosen in case the path ends with '/'
-            for(var i = requestPath.Length - 2; i >= 0; i--)
+            for (var i = requestPath.Length - 2; i >= 0; i--)
             {
                 // if there are not enough characters left in the path to 
                 // contain "relationships"
-                if(i < relationships.Length) 
+                if (i < relationships.Length)
                     return false;
 
                 // we have found the first instance of '/'
-                if(span[i] == pathSegmentDelimiter)
+                if (span[i] == pathSegmentDelimiter)
                 {
                     // in the case of a "relationships" route, the next
                     // path segment will be "relationships"
@@ -112,20 +112,18 @@ internal static bool PathIsRelationship(string requestPath)
 
             return false;
         }
-        
+
         private PageManager GetPageManager()
         {
             if (Options.DefaultPageSize == 0 && (QuerySet == null || QuerySet.PageQuery.PageSize == 0))
                 return new PageManager();
 
             var query = QuerySet?.PageQuery ?? new PageQuery();
-            var requestMethod = _httpContextAccessor.HttpContext.Request.Method;
 
             return new PageManager
             {
                 DefaultPageSize = Options.DefaultPageSize,
                 CurrentPage = query.PageOffset,
-                TotalRecords = (requestMethod == "POST" || requestMethod == "PATCH") ? 1 : 0,
                 PageSize = query.PageSize > 0 ? query.PageSize : Options.DefaultPageSize
             };
         }
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
index 013cd85bcb..5c74c2c715 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
@@ -48,7 +48,7 @@ public async Task Total_Record_Count_Included()
             var response = await client.SendAsync(request);
             var responseBody = await response.Content.ReadAsStringAsync();
             var documents = JsonConvert.DeserializeObject<Documents>(responseBody);
-            
+
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotNull(documents.Meta);
@@ -56,7 +56,7 @@ public async Task Total_Record_Count_Included()
         }
 
         [Fact]
-        public async Task Total_Record_Count_Not_Included_When_None()
+        public async Task Total_Record_Count_Included_When_None()
         {
             // arrange
             _context.TodoItems.RemoveRange(_context.TodoItems);
@@ -75,14 +75,15 @@ public async Task Total_Record_Count_Not_Included_When_None()
             var response = await client.SendAsync(request);
             var responseBody = await response.Content.ReadAsStringAsync();
             var documents = JsonConvert.DeserializeObject<Documents>(responseBody);
-            
+
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-            Assert.Null(documents.Meta);
+            Assert.NotNull(documents.Meta);
+            Assert.Equal(0, (long)documents.Meta["total-records"]);
         }
 
         [Fact]
-        public async Task Total_Record_Count_Included_POST()
+        public async Task Total_Record_Count_Not_Included_In_POST_Response()
         {
             // arrange
             _context.TodoItems.RemoveRange(_context.TodoItems);
@@ -116,15 +117,14 @@ public async Task Total_Record_Count_Included_POST()
             var response = await client.SendAsync(request);
             var responseBody = await response.Content.ReadAsStringAsync();
             var documents = JsonConvert.DeserializeObject<Document>(responseBody);
-            
+
             // assert
             Assert.Equal(HttpStatusCode.Created, response.StatusCode);
-            Assert.NotNull(documents.Meta);
-            Assert.Equal((long)expectedCount, (long)documents.Meta["total-records"]);
+            Assert.Null(documents.Meta);
         }
 
         [Fact]
-        public async Task Total_Record_Count_Included_PATCH()
+        public async Task Total_Record_Count_Not_Included_In_PATCH_Response()
         {
             // arrange
             _context.TodoItems.RemoveRange(_context.TodoItems);
@@ -161,11 +161,10 @@ public async Task Total_Record_Count_Included_PATCH()
             var response = await client.SendAsync(request);
             var responseBody = await response.Content.ReadAsStringAsync();
             var documents = JsonConvert.DeserializeObject<Document>(responseBody);
-            
+
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-            Assert.NotNull(documents.Meta);
-            Assert.Equal((long)expectedCount, (long)documents.Meta["total-records"]);
+            Assert.Null(documents.Meta);
         }
 
         [Fact]
@@ -187,26 +186,26 @@ public async Task EntityThatImplements_IHasMeta_Contains_MetaData()
             // act
             var response = await client.SendAsync(request);
             var documents = JsonConvert.DeserializeObject<Documents>(await response.Content.ReadAsStringAsync());
-            
+
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             Assert.NotNull(documents.Meta);
             Assert.NotNull(expectedMeta);
             Assert.NotEmpty(expectedMeta);
-            
-            foreach(var hash in expectedMeta)
+
+            foreach (var hash in expectedMeta)
             {
-                if(hash.Value is IList)
+                if (hash.Value is IList)
                 {
                     var listValue = (IList)hash.Value;
-                    for(var i=0; i < listValue.Count; i++)
+                    for (var i = 0; i < listValue.Count; i++)
                         Assert.Equal(listValue[i].ToString(), ((IList)documents.Meta[hash.Key])[i].ToString());
                 }
                 else
                 {
                     Assert.Equal(hash.Value, documents.Meta[hash.Key]);
                 }
-            }                
+            }
         }
     }
 }

From f0f8d9e45159063c6d10376e767783d3cca919ad Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 20 Jun 2018 18:44:27 -0500
Subject: [PATCH 198/227] allow TotalRecords to be 0

---
 src/JsonApiDotNetCore/Internal/PageManager.cs               | 2 +-
 .../Acceptance/Spec/DocumentTests/Meta.cs                   | 6 ++----
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/JsonApiDotNetCore/Internal/PageManager.cs b/src/JsonApiDotNetCore/Internal/PageManager.cs
index 1e35b71b4e..d27fc158fd 100644
--- a/src/JsonApiDotNetCore/Internal/PageManager.cs
+++ b/src/JsonApiDotNetCore/Internal/PageManager.cs
@@ -11,7 +11,7 @@ public class PageManager
         public int DefaultPageSize { get; set; }
         public int CurrentPage { get; set; }
         public bool IsPaginated => PageSize > 0;
-        public int TotalPages => (TotalRecords == 0 || TotalRecords == null) ? -1 : (int)Math.Ceiling(decimal.Divide(TotalRecords.Value, PageSize));
+        public int TotalPages => (TotalRecords == null) ? -1 : (int)Math.Ceiling(decimal.Divide(TotalRecords.Value, PageSize));
 
         public RootLinks GetPageLinks(LinkBuilder linkBuilder)
         {
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
index 5c74c2c715..2b6b1e251b 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs
@@ -88,7 +88,6 @@ public async Task Total_Record_Count_Not_Included_In_POST_Response()
             // arrange
             _context.TodoItems.RemoveRange(_context.TodoItems);
             _context.SaveChanges();
-            var expectedCount = 1;
             var builder = new WebHostBuilder()
                 .UseStartup<MetaStartup>();
 
@@ -120,7 +119,7 @@ public async Task Total_Record_Count_Not_Included_In_POST_Response()
 
             // assert
             Assert.Equal(HttpStatusCode.Created, response.StatusCode);
-            Assert.Null(documents.Meta);
+            Assert.False(documents.Meta.ContainsKey("total-records"));
         }
 
         [Fact]
@@ -131,7 +130,6 @@ public async Task Total_Record_Count_Not_Included_In_PATCH_Response()
             TodoItem todoItem = new TodoItem();
             _context.TodoItems.Add(todoItem);
             _context.SaveChanges();
-            var expectedCount = 1;
             var builder = new WebHostBuilder()
                 .UseStartup<MetaStartup>();
 
@@ -164,7 +162,7 @@ public async Task Total_Record_Count_Not_Included_In_PATCH_Response()
 
             // assert
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-            Assert.Null(documents.Meta);
+            Assert.False(documents.Meta.ContainsKey("total-records"));
         }
 
         [Fact]

From c47886a92d32a3a7d83a710544c2ed7a78a65bd3 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 20 Jun 2018 19:07:40 -0500
Subject: [PATCH 199/227] allow meta to be included even if there is no
 returned resource

---
 src/JsonApiDotNetCore/Builders/DocumentBuilder.cs | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 1a7a692101..c09cbefef3 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -68,21 +68,20 @@ public Documents Build(IEnumerable<IIdentifiable> entities)
 
         private Dictionary<string, object> GetMeta(IIdentifiable entity)
         {
-            if (entity == null) return null;
-
             var builder = _jsonApiContext.MetaBuilder;
-
-            if (entity is IHasMeta metaEntity)
-                builder.Add(metaEntity.GetMeta(_jsonApiContext));
-
             if (_jsonApiContext.Options.IncludeTotalRecordCount && _jsonApiContext.PageManager.TotalRecords != null)
                 builder.Add("total-records", _jsonApiContext.PageManager.TotalRecords);
 
             if (_requestMeta != null)
                 builder.Add(_requestMeta.GetMeta());
 
+            if (entity != null && entity is IHasMeta metaEntity)
+                builder.Add(metaEntity.GetMeta(_jsonApiContext));
+
             var meta = builder.Build();
-            if (meta.Count > 0) return meta;
+            if (meta.Count > 0)
+                return meta;
+
             return null;
         }
 

From e6fb9263a247dd98155cc18dfbe502395faf5305 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 20 Jun 2018 19:30:55 -0500
Subject: [PATCH 200/227] expect total-records to be included if configured

---
 .../Acceptance/Spec/FetchingDataTests.cs                    | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs
index 8573d0b560..9c8d5f8214 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs
@@ -53,8 +53,10 @@ public async Task Request_ForEmptyCollection_Returns_EmptyDataCollection()
             var server = new TestServer(builder);
             var client = server.CreateClient();
             var request = new HttpRequestMessage(httpMethod, route);
-            var expectedBody = JsonConvert.SerializeObject(new {
-                data = new List<object>()
+            var expectedBody = JsonConvert.SerializeObject(new
+            {
+                data = new List<object>(),
+                meta = new Dictionary<string, int> { { "total-records", 0 } }
             });
 
             // act

From e3e3c95850c7832e06dbbac15337df486d206368 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 27 Jun 2018 10:23:12 -0700
Subject: [PATCH 201/227] fix(#312): deserializer not handling included
 relationships

---
 .../Builders/DocumentBuilder.cs               |  13 +-
 .../Data/DefaultEntityRepository.cs           |  14 +-
 .../IServiceCollectionExtensions.cs           |   1 -
 .../Extensions/TypeExtensions.cs              |  17 ++-
 .../Internal/Generics/GenericProcessor.cs     |  11 +-
 src/JsonApiDotNetCore/Models/Identifiable.cs  |   9 +-
 .../Models/RelationshipAttribute.cs           |  11 ++
 .../Serialization/IJsonApiDeSerializer.cs     |   4 +-
 .../Serialization/JsonApiDeSerializer.cs      | 123 ++++++++++++-----
 .../Serialization/JsonApiDeSerializerTests.cs | 127 +++++++++++++++++-
 .../Processors/CreateOpProcessorTests.cs      |   4 +-
 11 files changed, 272 insertions(+), 62 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 0beb0516c1..8142b2ea26 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -262,11 +262,14 @@ private ResourceIdentifierObject GetRelationship(object entity)
             var objType = entity.GetType();
             var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(objType);
 
-            return new ResourceIdentifierObject
-            {
-                Type = contextEntity.EntityName,
-                Id = ((IIdentifiable)entity).StringId
-            };
+            if(entity is IIdentifiable identifiableEntity)
+                return new ResourceIdentifierObject
+                {
+                    Type = contextEntity.EntityName,
+                    Id = identifiableEntity.StringId
+                };
+
+            return null;
         }
 
         private ResourceIdentifierObject GetIndependentRelationshipIdentifier(HasOneAttribute hasOne, IIdentifiable entity)
diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index 032fef13c4..e6d534172f 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -185,17 +185,23 @@ public virtual async Task<IEnumerable<TEntity>> PageAsync(IQueryable<TEntity> en
 
         public async Task<int> CountAsync(IQueryable<TEntity> entities)
         {
-            return await entities.CountAsync();
+            return (entities is IAsyncEnumerable<TEntity>)
+                 ? await entities.CountAsync()
+                 : entities.Count();
         }
 
-        public Task<TEntity> FirstOrDefaultAsync(IQueryable<TEntity> entities)
+        public async Task<TEntity> FirstOrDefaultAsync(IQueryable<TEntity> entities)
         {
-            return entities.FirstOrDefaultAsync();
+            return (entities is IAsyncEnumerable<TEntity>)
+               ? await entities.FirstOrDefaultAsync()
+               : entities.FirstOrDefault();
         }
 
         public async Task<IReadOnlyList<TEntity>> ToListAsync(IQueryable<TEntity> entities)
         {
-            return await entities.ToListAsync();
+            return (entities is IAsyncEnumerable<TEntity>)
+                ? await entities.ToListAsync()
+                : entities.ToList();
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 5e8eeefdd1..ea15036201 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -136,7 +136,6 @@ public static void AddJsonApiInternals(
             services.AddScoped<IJsonApiReader, JsonApiReader>();
             services.AddScoped<IGenericProcessorFactory, GenericProcessorFactory>();
             services.AddScoped(typeof(GenericProcessor<>));
-            services.AddScoped(typeof(GenericProcessor<,>));
             services.AddScoped<IQueryAccessor, QueryAccessor>();
             services.AddScoped<IQueryParser, QueryParser>();
             services.AddScoped<IControllerContext, Services.ControllerContext>();
diff --git a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
index 8cc7c0dffe..74c390e8d5 100644
--- a/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/TypeExtensions.cs
@@ -1,4 +1,5 @@
-using System;
+using JsonApiDotNetCore.Internal;
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -51,8 +52,20 @@ public static TInterface New<TInterface>(this Type t)
         {
             if (t == null) throw new ArgumentNullException(nameof(t));
 
-            var instance = (TInterface)Activator.CreateInstance(t);
+            var instance = (TInterface)CreateNewInstance(t);
             return instance;
         }
+
+        private static object CreateNewInstance(Type type)
+        {
+            try
+            {
+                return Activator.CreateInstance(type);
+            }
+            catch (Exception e)
+            {
+                throw new JsonApiException(500, $"Type '{type}' cannot be instantiated using the default constructor.", e);
+            }
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
index 8e5d17e56b..1aa6610790 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
@@ -14,12 +14,7 @@ public interface IGenericProcessor
         void SetRelationships(object parent, RelationshipAttribute relationship, IEnumerable<string> relationshipIds);
     }
 
-    public class GenericProcessor<T> : GenericProcessor<T, int> where T : class, IIdentifiable<int>
-    {
-        public GenericProcessor(IDbContextResolver contextResolver) : base(contextResolver) { }
-    }
-
-    public class GenericProcessor<T, TId> : IGenericProcessor where T : class, IIdentifiable<TId>
+    public class GenericProcessor<T> : IGenericProcessor where T : class, IIdentifiable
     {
         private readonly DbContext _context;
         public GenericProcessor(IDbContextResolver contextResolver)
@@ -38,12 +33,12 @@ public void SetRelationships(object parent, RelationshipAttribute relationship,
         {
             if (relationship.IsHasMany)
             {
-                var entities = _context.GetDbSet<T>().Where(x => relationshipIds.Contains(x.StringId)).ToList();
+                var entities = _context.Set<T>().Where(x => relationshipIds.Contains(x.StringId)).ToList();
                 relationship.SetValue(parent, entities);
             }
             else
             {
-                var entity = _context.GetDbSet<T>().SingleOrDefault(x => relationshipIds.First() == x.StringId);
+                var entity = _context.Set<T>().SingleOrDefault(x => relationshipIds.First() == x.StringId);
                 relationship.SetValue(parent, entity);
             }
         }
diff --git a/src/JsonApiDotNetCore/Models/Identifiable.cs b/src/JsonApiDotNetCore/Models/Identifiable.cs
index 0adb073f2f..703cc2f051 100644
--- a/src/JsonApiDotNetCore/Models/Identifiable.cs
+++ b/src/JsonApiDotNetCore/Models/Identifiable.cs
@@ -15,7 +15,7 @@ public class Identifiable<T> : IIdentifiable<T>
         public string StringId
         {
             get => GetStringId(Id);
-            set => Id = (T)GetConcreteId(value);
+            set => Id = GetTypedId(value);
         }
 
         protected virtual string GetStringId(object value)
@@ -34,6 +34,13 @@ protected virtual string GetStringId(object value)
                 : stringValue;
         }
 
+        protected virtual T GetTypedId(string value)
+        {
+            var convertedValue = TypeHelper.ConvertType(value, typeof(T));
+            return convertedValue == null ? default : (T)convertedValue;
+        }
+
+        [Obsolete("Use GetTypedId instead")]
         protected virtual object GetConcreteId(string value)
         {
             return TypeHelper.ConvertType(value, typeof(T));
diff --git a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
index 3e66bdc8aa..65a170281e 100644
--- a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs
@@ -13,6 +13,17 @@ protected RelationshipAttribute(string publicName, Link documentLinks, bool canI
 
         public string PublicRelationshipName { get; }
         public string InternalRelationshipName { get; internal set; }
+
+        /// <summary>
+        /// The related entity type. This does not necessarily match the navigation property type.
+        /// In the case of a HasMany relationship, this value will be the generic argument type.
+        /// </summary>
+        /// 
+        /// <example>
+        /// <code>
+        /// public List&lt;Articles&gt; Articles { get; set; } // Type => Article
+        /// </code>
+        /// </example>
         public Type Type { get; internal set; }
         public bool IsHasMany => GetType() == typeof(HasManyAttribute);
         public bool IsHasOne => GetType() == typeof(HasOneAttribute);
diff --git a/src/JsonApiDotNetCore/Serialization/IJsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/IJsonApiDeSerializer.cs
index 0355c962ed..57b28c6087 100644
--- a/src/JsonApiDotNetCore/Serialization/IJsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/IJsonApiDeSerializer.cs
@@ -9,6 +9,6 @@ public interface IJsonApiDeSerializer
         TEntity Deserialize<TEntity>(string requestBody);
         object DeserializeRelationship(string requestBody);
         List<TEntity> DeserializeList<TEntity>(string requestBody);
-        object DocumentToObject(DocumentData data);
+        object DocumentToObject(DocumentData data, List<DocumentData> included = null);
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 45d77c0f77..f7a54ffbd3 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -54,7 +54,7 @@ public object Deserialize(string requestBody)
                 var document = bodyJToken.ToObject<Document>();
 
                 _jsonApiContext.DocumentMeta = document.Meta;
-                var entity = DocumentToObject(document.Data);
+                var entity = DocumentToObject(document.Data, document.Included);
                 return entity;
             }
             catch (Exception e)
@@ -95,8 +95,8 @@ public List<TEntity> DeserializeList<TEntity>(string requestBody)
                 var deserializedList = new List<TEntity>();
                 foreach (var data in documents.Data)
                 {
-                    var entity = DocumentToObject(data);
-                    deserializedList.Add((TEntity)entity);
+                    var entity = (TEntity)DocumentToObject(data, documents.Included);
+                    deserializedList.Add(entity);
                 }
 
                 return deserializedList;
@@ -107,7 +107,7 @@ public List<TEntity> DeserializeList<TEntity>(string requestBody)
             }
         }
 
-        public object DocumentToObject(DocumentData data)
+        public object DocumentToObject(DocumentData data, List<DocumentData> included = null)
         {
             if (data == null) throw new JsonApiException(422, "Failed to deserialize document as json:api.");
 
@@ -117,7 +117,7 @@ public object DocumentToObject(DocumentData data)
             var entity = Activator.CreateInstance(contextEntity.EntityType);
 
             entity = SetEntityAttributes(entity, contextEntity, data.Attributes);
-            entity = SetRelationships(entity, contextEntity, data.Relationships);
+            entity = SetRelationships(entity, contextEntity, data.Relationships, included);
 
             var identifiableEntity = (IIdentifiable)entity;
 
@@ -172,7 +172,8 @@ private object DeserializeComplexType(JContainer obj, Type targetType)
         private object SetRelationships(
             object entity,
             ContextEntity contextEntity,
-            Dictionary<string, RelationshipData> relationships)
+            Dictionary<string, RelationshipData> relationships, 
+            List<DocumentData> included = null)
         {
             if (relationships == null || relationships.Count == 0)
                 return entity;
@@ -182,8 +183,8 @@ private object SetRelationships(
             foreach (var attr in contextEntity.Relationships)
             {
                 entity = attr.IsHasOne
-                    ? SetHasOneRelationship(entity, entityProperties, (HasOneAttribute)attr, contextEntity, relationships)
-                    : SetHasManyRelationship(entity, entityProperties, attr, contextEntity, relationships);
+                    ? SetHasOneRelationship(entity, entityProperties, (HasOneAttribute)attr, contextEntity, relationships, included)
+                    : SetHasManyRelationship(entity, entityProperties, attr, contextEntity, relationships, included);
             }
 
             return entity;
@@ -193,39 +194,53 @@ private object SetHasOneRelationship(object entity,
             PropertyInfo[] entityProperties,
             HasOneAttribute attr,
             ContextEntity contextEntity,
-            Dictionary<string, RelationshipData> relationships)
+            Dictionary<string, RelationshipData> relationships,
+            List<DocumentData> included = null)
         {
             var relationshipName = attr.PublicRelationshipName;
 
-            if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
-            {
-                var relationshipAttr = _jsonApiContext.RequestEntity.Relationships
-                    .SingleOrDefault(r => r.PublicRelationshipName == relationshipName);
+            if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData) == false)
+                return entity;
+            
+            var relationshipAttr = _jsonApiContext.RequestEntity.Relationships
+                .SingleOrDefault(r => r.PublicRelationshipName == relationshipName);
 
-                if (relationshipAttr == null)
-                    throw new JsonApiException(400, $"{_jsonApiContext.RequestEntity.EntityName} does not contain a relationship '{relationshipName}'");
+            if (relationshipAttr == null)
+                throw new JsonApiException(400, $"{_jsonApiContext.RequestEntity.EntityName} does not contain a relationship '{relationshipName}'");
 
-                var rio = (ResourceIdentifierObject)relationshipData.ExposedData;
+            var rio = (ResourceIdentifierObject)relationshipData.ExposedData;
 
-                var foreignKey = attr.IdentifiablePropertyName;
-                var entityProperty = entityProperties.FirstOrDefault(p => p.Name == foreignKey);
-                if (entityProperty == null && rio != null)
-                    throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a foreign key property '{foreignKey}' for has one relationship '{attr.InternalRelationshipName}'");
+            var foreignKey = attr.IdentifiablePropertyName;
+            var foreignKeyProperty = entityProperties.FirstOrDefault(p => p.Name == foreignKey);
 
-                if (entityProperty != null)
-                {
-                    // e.g. PATCH /articles
-                    // {... { "relationships":{ "Owner": { "data" :null } } } }
-                    if (rio == null && Nullable.GetUnderlyingType(entityProperty.PropertyType) == null)
-                        throw new JsonApiException(400, $"Cannot set required relationship identifier '{attr.IdentifiablePropertyName}' to null.");
+            if (foreignKeyProperty == null && rio == null)
+                return entity;
 
-                    var newValue = rio?.Id ?? null;
-                    var convertedValue = TypeHelper.ConvertType(newValue, entityProperty.PropertyType);
+            if (foreignKeyProperty == null && rio != null)
+                throw new JsonApiException(400, $"{contextEntity.EntityType.Name} does not contain a foreign key property '{foreignKey}' for has one relationship '{attr.InternalRelationshipName}'");
 
-                    _jsonApiContext.RelationshipsToUpdate[relationshipAttr] = convertedValue;
+            // e.g. PATCH /articles
+            // {... { "relationships":{ "Owner": { "data": null } } } }
+            if (rio == null && Nullable.GetUnderlyingType(foreignKeyProperty.PropertyType) == null)
+                throw new JsonApiException(400, $"Cannot set required relationship identifier '{attr.IdentifiablePropertyName}' to null because it is a non-nullable type.");
 
-                    entityProperty.SetValue(entity, convertedValue);
-                }
+            var newValue = rio?.Id ?? null;
+            var convertedValue = TypeHelper.ConvertType(newValue, foreignKeyProperty.PropertyType);
+
+            _jsonApiContext.RelationshipsToUpdate[relationshipAttr] = convertedValue;
+
+            foreignKeyProperty.SetValue(entity, convertedValue);
+
+
+            if(rio != null
+                // if the resource identifier is null, there should be no reason to instantiate an instance
+                && rio.Id != null)
+            {
+                // we have now set the FK property on the resource, now we need to check to see if the
+                // related entity was included in the payload and update its attributes
+                var includedRelationshipObject = GetIncludedRelationship(rio, included, relationshipAttr);
+                if (includedRelationshipObject != null)
+                    relationshipAttr.SetValue(entity, includedRelationshipObject);
             }
 
             return entity;
@@ -235,7 +250,8 @@ private object SetHasManyRelationship(object entity,
             PropertyInfo[] entityProperties,
             RelationshipAttribute attr,
             ContextEntity contextEntity,
-            Dictionary<string, RelationshipData> relationships)
+            Dictionary<string, RelationshipData> relationships,
+            List<DocumentData> included = null)
         {
             var relationshipName = attr.PublicRelationshipName;
 
@@ -245,14 +261,13 @@ private object SetHasManyRelationship(object entity,
 
                 if (data == null) return entity;
 
-                var relationshipShells = relationshipData.ManyData.Select(r =>
+                var relatedResources = relationshipData.ManyData.Select(r =>
                 {
-                    var instance = attr.Type.New<IIdentifiable>();
-                    instance.StringId = r.Id;
+                    var instance = GetIncludedRelationship(r, included, attr);
                     return instance;
                 });
 
-                var convertedCollection = TypeHelper.ConvertCollection(relationshipShells, attr.Type);
+                var convertedCollection = TypeHelper.ConvertCollection(relatedResources, attr.Type);
 
                 attr.SetValue(entity, convertedCollection);
 
@@ -261,5 +276,41 @@ private object SetHasManyRelationship(object entity,
 
             return entity;
         }
+
+        private IIdentifiable GetIncludedRelationship(ResourceIdentifierObject relatedResourceIdentifier, List<DocumentData> includedResources, RelationshipAttribute relationshipAttr)
+        {
+            // at this point we can be sure the relationshipAttr.Type is IIdentifiable because we were able to successfully build the ContextGraph
+            var relatedInstance = relationshipAttr.Type.New<IIdentifiable>();
+            relatedInstance.StringId = relatedResourceIdentifier.Id;
+
+            // can't provide any more data other than the rio since it is not contained in the included section
+            if (includedResources == null || includedResources.Count == 0)
+                return relatedInstance;
+
+            var includedResource = GetLinkedResource(relatedResourceIdentifier, includedResources);
+            if (includedResource == null)
+                return relatedInstance;
+
+            var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(relationshipAttr.Type);
+            if (contextEntity == null)
+                throw new JsonApiException(400, $"Included type '{relationshipAttr.Type}' is not a registered json:api resource.");
+            
+            SetEntityAttributes(relatedInstance, contextEntity, includedResource.Attributes);
+
+            return relatedInstance;
+        }
+
+        private DocumentData GetLinkedResource(ResourceIdentifierObject relatedResourceIdentifier, List<DocumentData> includedResources)
+        {
+            try
+            {
+                return includedResources.SingleOrDefault(r => r.Type == relatedResourceIdentifier.Type && r.Id == relatedResourceIdentifier.Id);
+            }
+            catch (InvalidOperationException e)
+            {
+                throw new JsonApiException(400, $"A compound document MUST NOT include more than one resource object for each type and id pair."
+                        + $"The duplicate pair was '{relatedResourceIdentifier.Type}, {relatedResourceIdentifier.Id}'", e);
+            }
+        }
     }
 }
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index be16d1d9d7..58955bc4e2 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -392,20 +392,145 @@ public void Can_Deserialize_Object_With_HasManyRelationship()
             Assert.Equal(1, result.Id);
             Assert.NotNull(result.Dependents);
             Assert.NotEmpty(result.Dependents);
-            Assert.Equal(1, result.Dependents.Count);
+            Assert.Single(result.Dependents);
 
             var dependent = result.Dependents[0];
             Assert.Equal(2, dependent.Id);
         }
 
+        [Fact]
+        public void Sets_Attribute_Values_On_Included_HasMany_Relationships()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<OneToManyIndependent>("independents");
+            contextGraphBuilder.AddResource<OneToManyDependent>("dependents");
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+            jsonApiContextMock.Setup(m => m.HasManyRelationshipPointers).Returns(new HasManyRelationshipPointers());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
+
+            var expectedName = "John Doe";
+            var contentString =
+            @"{
+                ""data"": {
+                    ""type"": ""independents"",
+                    ""id"": ""1"",
+                    ""attributes"": { },
+                    ""relationships"": {
+                        ""dependents"": {
+                            ""data"": [
+                                {
+                                    ""type"": ""dependents"",
+                                    ""id"": ""2""
+                                }
+                            ]
+                        }
+                    }
+                },
+                ""included"": [
+                    {
+                        ""type"": ""dependents"",
+                        ""id"": ""2"",
+                        ""attributes"": {
+                            ""name"": """ + expectedName + @"""
+                        }
+                    }
+                ]
+            }";
+
+            // act
+            var result = deserializer.Deserialize<OneToManyIndependent>(contentString);
+
+            // assert
+            Assert.NotNull(result);
+            Assert.Equal(1, result.Id);
+            Assert.NotNull(result.Dependents);
+            Assert.NotEmpty(result.Dependents);
+            Assert.Single(result.Dependents);
+
+            var dependent = result.Dependents[0];
+            Assert.Equal(2, dependent.Id);
+            Assert.Equal(expectedName, dependent.Name);
+        }
+
+        [Fact]
+        public void Sets_Attribute_Values_On_Included_HasOne_Relationships()
+        {
+            // arrange
+            var contextGraphBuilder = new ContextGraphBuilder();
+            contextGraphBuilder.AddResource<OneToManyIndependent>("independents");
+            contextGraphBuilder.AddResource<OneToManyDependent>("dependents");
+            var contextGraph = contextGraphBuilder.Build();
+
+            var jsonApiContextMock = new Mock<IJsonApiContext>();
+            jsonApiContextMock.SetupAllProperties();
+            jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+            jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
+            jsonApiContextMock.Setup(m => m.RelationshipsToUpdate).Returns(new Dictionary<RelationshipAttribute, object>());
+            jsonApiContextMock.Setup(m => m.HasManyRelationshipPointers).Returns(new HasManyRelationshipPointers());
+
+            var jsonApiOptions = new JsonApiOptions();
+            jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
+
+            var deserializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
+
+            var expectedName = "John Doe";
+            var contentString =
+            @"{
+                ""data"": {
+                    ""type"": ""dependents"",
+                    ""id"": ""1"",
+                    ""attributes"": { },
+                    ""relationships"": {
+                        ""independent"": {
+                            ""data"": {
+                                ""type"": ""independents"",
+                                ""id"": ""2""
+                            }
+                        }
+                    }
+                },
+                ""included"": [
+                    {
+                        ""type"": ""independents"",
+                        ""id"": ""2"",
+                        ""attributes"": {
+                            ""name"": """ + expectedName + @"""
+                        }
+                    }
+                ]
+            }";
+
+            // act
+            var result = deserializer.Deserialize<OneToManyDependent>(contentString);
+
+            // assert
+            Assert.NotNull(result);
+            Assert.Equal(1, result.Id);
+            Assert.NotNull(result.Independent);
+            Assert.Equal(2, result.Independent.Id);
+            Assert.Equal(expectedName, result.Independent.Name);
+        }
+
         private class OneToManyDependent : Identifiable
         {
+            [Attr("name")] public string Name { get; set; }
             [HasOne("independent")] public OneToManyIndependent Independent { get; set; }
             public int IndependentId { get; set; }
         }
 
         private class OneToManyIndependent : Identifiable
         {
+            [Attr("name")] public string Name { get; set; }
             [HasMany("dependents")] public List<OneToManyDependent> Dependents { get; set; }
         }
     }
diff --git a/test/UnitTests/Services/Operations/Processors/CreateOpProcessorTests.cs b/test/UnitTests/Services/Operations/Processors/CreateOpProcessorTests.cs
index 9e33af63c2..aa76f2dc17 100644
--- a/test/UnitTests/Services/Operations/Processors/CreateOpProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/Processors/CreateOpProcessorTests.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Internal;
@@ -48,7 +48,7 @@ public async Task ProcessAsync_Deserializes_And_Creates()
                 .AddResource<TestResource>("test-resources")
                 .Build();
 
-            _deserializerMock.Setup(m => m.DocumentToObject(It.IsAny<DocumentData>()))
+            _deserializerMock.Setup(m => m.DocumentToObject(It.IsAny<DocumentData>(), It.IsAny<List<DocumentData>>()))
                 .Returns(testResource);
 
             var opProcessor = new CreateOpProcessor<TestResource>(

From d8b045ffdbbfbada6adccfad6793189137b1baef Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 27 Jun 2018 15:09:45 -0700
Subject: [PATCH 202/227] handle attaching HasOne relationships

---
 .../Data/DefaultEntityRepository.cs           | 20 +++++++-
 .../Extensions/DbContextExtensions.cs         | 21 +++++++++
 .../Request/HasOneRelationshipPointers.cs     | 46 +++++++++++++++++++
 .../Serialization/JsonApiDeSerializer.cs      |  5 ++
 .../Services/IJsonApiContext.cs               | 25 ++++++++++
 .../Services/JsonApiContext.cs                |  1 +
 .../Acceptance/TodoItemsControllerTests.cs    |  5 +-
 .../Serialization/JsonApiDeSerializerTests.cs |  1 +
 8 files changed, 121 insertions(+), 3 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Request/HasOneRelationshipPointers.cs

diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index e6d534172f..d1b82e30bc 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -84,13 +84,19 @@ public virtual async Task<TEntity> GetAndIncludeAsync(TId id, string relationshi
 
         public virtual async Task<TEntity> CreateAsync(TEntity entity)
         {
-            AttachHasManyPointers();
+            AttachRelationships();
             _dbSet.Add(entity);
 
             await _context.SaveChangesAsync();
             return entity;
         }
 
+        protected virtual void AttachRelationships()
+        {
+            AttachHasManyPointers();
+            AttachHasOnePointers();
+        }
+
         /// <summary>
         /// This is used to allow creation of HasMany relationships when the
         /// dependent side of the relationship already exists.
@@ -107,6 +113,18 @@ private void AttachHasManyPointers()
             }
         }
 
+        /// <summary>
+        /// This is used to allow creation of HasOne relationships when the
+        /// independent side of the relationship already exists.
+        /// </summary>
+        private void AttachHasOnePointers()
+        {
+            var relationships = _jsonApiContext.HasOneRelationshipPointers.Get();
+            foreach (var relationship in relationships)
+                if (_context.Entry(relationship.Value).State == EntityState.Detached && _context.EntityIsTracked(relationship.Value) == false)
+                    _context.Entry(relationship.Value).State = EntityState.Unchanged;
+        }
+
         public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
         {
             var oldEntity = await GetAsync(id);
diff --git a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
index 3cb5ccc359..2756524dce 100644
--- a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
@@ -1,4 +1,7 @@
 using System;
+using System.Linq;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCore.Extensions
@@ -8,5 +11,23 @@ public static class DbContextExtensions
         [Obsolete("This is no longer required since the introduction of context.Set<T>", error: false)]
         public static DbSet<T> GetDbSet<T>(this DbContext context) where T : class 
             => context.Set<T>();
+
+        /// <summary>
+        /// Determines whether or not EF is already tracking an entity of the same Type and Id
+        /// </summary>
+        public static bool EntityIsTracked(this DbContext context, IIdentifiable entity)
+        {
+            if (entity == null)
+                throw new ArgumentNullException(nameof(entity));
+            
+            var trackedEntries = context.ChangeTracker
+                .Entries()
+                .FirstOrDefault(entry => 
+                    entry.Entity.GetType() == entity.GetType() 
+                    && ((IIdentifiable)entry.Entity).StringId == entity.StringId
+                );
+
+            return trackedEntries != null;
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Request/HasOneRelationshipPointers.cs b/src/JsonApiDotNetCore/Request/HasOneRelationshipPointers.cs
new file mode 100644
index 0000000000..9e0bdd0e15
--- /dev/null
+++ b/src/JsonApiDotNetCore/Request/HasOneRelationshipPointers.cs
@@ -0,0 +1,46 @@
+using JsonApiDotNetCore.Models;
+using System;
+using System.Collections.Generic;
+
+namespace JsonApiDotNetCore.Request
+{
+    /// <summary>
+    /// Stores information to set relationships for the request resource. 
+    /// These relationships must already exist and should not be re-created.
+    /// 
+    /// The expected use case is POST-ing or PATCH-ing 
+    /// an entity with HasOne relationships:
+    /// <code>
+    /// {
+    ///    "data": {
+    ///      "type": "photos",
+    ///      "attributes": {
+    ///        "title": "Ember Hamster",
+    ///        "src": "http://example.com/images/productivity.png"
+    ///      },
+    ///      "relationships": {
+    ///        "photographer": {
+    ///          "data": { "type": "people", "id": "2" }
+    ///        }
+    ///      }
+    ///    }
+    ///  }
+    /// </code>
+    /// </summary>
+    public class HasOneRelationshipPointers
+    {
+        private Dictionary<Type, IIdentifiable> _hasOneRelationships = new Dictionary<Type, IIdentifiable>();
+
+        /// <summary>
+        /// Add the relationship to the list of relationships that should be 
+        /// set in the repository layer.
+        /// </summary>
+        public void Add(Type dependentType, IIdentifiable entity)
+            => _hasOneRelationships[dependentType] = entity;
+
+        /// <summary>
+        /// Get all the models that should be associated
+        /// </summary>
+        public Dictionary<Type, IIdentifiable> Get() => _hasOneRelationships;
+    }
+}
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index f7a54ffbd3..a1e3c76214 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -241,6 +241,11 @@ private object SetHasOneRelationship(object entity,
                 var includedRelationshipObject = GetIncludedRelationship(rio, included, relationshipAttr);
                 if (includedRelationshipObject != null)
                     relationshipAttr.SetValue(entity, includedRelationshipObject);
+
+                // we need to store the fact that this relationship was included in the payload
+                // for EF, the repository will use these pointers to make ensure we don't try to
+                // create resources if they already exist, we just need to create the relationship
+                _jsonApiContext.HasOneRelationshipPointers.Add(attr.Type, includedRelationshipObject);
             }
 
             return entity;
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index 52036f21af..9cbe2a53ca 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -81,6 +81,31 @@ public interface IJsonApiRequest : IJsonApiApplication, IUpdateRequest, IQueryRe
         /// </summary>
         HasManyRelationshipPointers HasManyRelationshipPointers { get; }
 
+        /// <summary>
+        /// Stores information to set relationships for the request resource. 
+        /// These relationships must already exist and should not be re-created.
+        /// 
+        /// The expected use case is POST-ing or PATCH-ing 
+        /// an entity with HasOne relationships:
+        /// <code>
+        /// {
+        ///    "data": {
+        ///      "type": "photos",
+        ///      "attributes": {
+        ///        "title": "Ember Hamster",
+        ///        "src": "http://example.com/images/productivity.png"
+        ///      },
+        ///      "relationships": {
+        ///        "photographer": {
+        ///          "data": { "type": "people", "id": "2" }
+        ///        }
+        ///      }
+        ///    }
+        ///  }
+        /// </code>
+        /// </summary>
+        HasOneRelationshipPointers HasOneRelationshipPointers { get; }
+
         /// <summary>
         /// If the request is a bulk json:api v1.1 operations request.
         /// This is determined by the `
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 0643d494d6..f579d8c9a2 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -53,6 +53,7 @@ public JsonApiContext(
         public Dictionary<string, object> DocumentMeta { get; set; }
         public bool IsBulkOperationRequest { get; set; }
         public HasManyRelationshipPointers HasManyRelationshipPointers { get; } = new HasManyRelationshipPointers();
+        public HasOneRelationshipPointers HasOneRelationshipPointers { get; } = new HasOneRelationshipPointers();
 
         public IJsonApiContext ApplyContext<T>(object controller)
         {
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
index acd37a535a..672492df16 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
@@ -294,11 +294,12 @@ public async Task Can_Post_TodoItem()
 
             // Act
             var response = await _fixture.Client.SendAsync(request);
-            var body = await response.Content.ReadAsStringAsync();
-            var deserializedBody = (TodoItem)_fixture.GetService<IJsonApiDeSerializer>().Deserialize(body);
 
             // Assert
             Assert.Equal(HttpStatusCode.Created, response.StatusCode);
+            var body = await response.Content.ReadAsStringAsync();
+            var deserializedBody = (TodoItem)_fixture.GetService<IJsonApiDeSerializer>().Deserialize(body);
+            Assert.Equal(HttpStatusCode.Created, response.StatusCode);
             Assert.Equal(todoItem.Description, deserializedBody.Description);
             Assert.Equal(todoItem.CreatedDate.ToString("G"), deserializedBody.CreatedDate.ToString("G"));
             Assert.Null(deserializedBody.AchievedDate);
diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
index 58955bc4e2..2da434c765 100644
--- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
+++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs
@@ -477,6 +477,7 @@ public void Sets_Attribute_Values_On_Included_HasOne_Relationships()
             jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
             jsonApiContextMock.Setup(m => m.RelationshipsToUpdate).Returns(new Dictionary<RelationshipAttribute, object>());
             jsonApiContextMock.Setup(m => m.HasManyRelationshipPointers).Returns(new HasManyRelationshipPointers());
+            jsonApiContextMock.Setup(m => m.HasOneRelationshipPointers).Returns(new HasOneRelationshipPointers());
 
             var jsonApiOptions = new JsonApiOptions();
             jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);

From c2b90846bca43d1f31df870ba22dc26625f68118 Mon Sep 17 00:00:00 2001
From: Simon Gent <simon.gent@gmail.com>
Date: Thu, 28 Jun 2018 08:23:22 +0100
Subject: [PATCH 203/227] Check if Model State is valid and throw a 400

---
 .../Controllers/BaseJsonApiController.cs      |  3 +
 .../Extensions/ModelStateExtensions.cs        | 23 +++++++
 .../JsonApiDotNetCore.csproj                  |  2 +-
 .../BaseJsonApiController_Tests.cs            | 62 +++++++++++++++++++
 4 files changed, 89 insertions(+), 1 deletion(-)
 create mode 100644 src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs

diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
index 760f8f8d56..45f16e29ec 100644
--- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
+++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
@@ -152,6 +153,7 @@ public virtual async Task<IActionResult> PostAsync([FromBody] T entity)
 
             if (!_jsonApiContext.Options.AllowClientGeneratedIds && !string.IsNullOrEmpty(entity.StringId))
                 return Forbidden();
+            if (!ModelState.IsValid) return BadRequest(ModelState.ConvertToErrorCollection());
 
             entity = await _create.CreateAsync(entity);
 
@@ -164,6 +166,7 @@ public virtual async Task<IActionResult> PatchAsync(TId id, [FromBody] T entity)
 
             if (entity == null)
                 return UnprocessableEntity();
+            if (!ModelState.IsValid) return BadRequest(ModelState.ConvertToErrorCollection());
 
             var updatedEntity = await _update.UpdateAsync(id, entity);
 
diff --git a/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs b/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs
new file mode 100644
index 0000000000..0ccdc224eb
--- /dev/null
+++ b/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs
@@ -0,0 +1,23 @@
+using JsonApiDotNetCore.Internal;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+using Microsoft.EntityFrameworkCore.Internal;
+
+namespace JsonApiDotNetCore.Extensions
+{
+    public static class ModelStateExtensions
+    {
+        public static ErrorCollection ConvertToErrorCollection(this ModelStateDictionary modelState)
+        {
+            ErrorCollection errors = new ErrorCollection();
+            foreach (var entry in modelState)
+            {
+                if (!entry.Value.Errors.Any()) continue;
+                foreach (var modelError in entry.Value.Errors)
+                {
+                    errors.Errors.Add(new Error(400, entry.Key, modelError.ErrorMessage, modelError.Exception != null ? ErrorMeta.FromException(modelError.Exception) : null));
+                }
+            }
+            return errors;
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 7019a8e6cc..75fc955402 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.3.1</VersionPrefix>
+    <VersionPrefix>2.3.2</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>
diff --git a/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs b/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
index 9c59372846..4edfeddbe7 100644
--- a/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
+++ b/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
@@ -5,7 +5,10 @@
 using Moq;
 using Xunit;
 using System.Threading.Tasks;
+using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Internal;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
 
 namespace UnitTests
 {
@@ -153,6 +156,25 @@ public async Task PatchAsync_Calls_Service()
             VerifyApplyContext();
         }
 
+        [Fact]
+        public async Task PatchAsync_ModelStateInvalid()
+        {
+            // arrange
+            const int id = 0;
+            var resource = new Resource();
+            var serviceMock = new Mock<IUpdateService<Resource>>();
+            var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, update: serviceMock.Object);
+            controller.ModelState.AddModelError("Id", "Failed Validation");
+
+            // act
+            var response = await controller.PatchAsync(id, resource);
+
+            // assert
+            serviceMock.Verify(m => m.UpdateAsync(id, It.IsAny<Resource>()), Times.Never);
+            Assert.IsType<BadRequestObjectResult>(response);
+            Assert.IsType<ErrorCollection>(((BadRequestObjectResult) response).Value);
+        }
+
         [Fact]
         public async Task PatchAsync_Throws_405_If_No_Service()
         {
@@ -168,6 +190,46 @@ public async Task PatchAsync_Throws_405_If_No_Service()
             Assert.Equal(405, exception.GetStatusCode());
         }
 
+        [Fact]
+        public async Task PostAsync_Calls_Service()
+        {
+            // arrange
+            var resource = new Resource();
+            var serviceMock = new Mock<ICreateService<Resource>>();
+            _jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
+            _jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions());
+            var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, create: serviceMock.Object);
+            serviceMock.Setup(m => m.CreateAsync(It.IsAny<Resource>())).ReturnsAsync(resource);
+            controller.ControllerContext = new Microsoft.AspNetCore.Mvc.ControllerContext {HttpContext = new DefaultHttpContext()};
+
+            // act
+            await controller.PostAsync(resource);
+
+            // assert
+            serviceMock.Verify(m => m.CreateAsync(It.IsAny<Resource>()), Times.Once);
+            VerifyApplyContext();
+        }
+
+        [Fact]
+        public async Task PostAsync_ModelStateInvalid()
+        {
+            // arrange
+            var resource = new Resource();
+            var serviceMock = new Mock<ICreateService<Resource>>();
+            _jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
+            _jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions());
+            var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, create: serviceMock.Object);
+            controller.ModelState.AddModelError("Id", "Failed Validation");
+
+            // act
+            var response = await controller.PostAsync(resource);
+
+            // assert
+            serviceMock.Verify(m => m.CreateAsync(It.IsAny<Resource>()), Times.Never);
+            Assert.IsType<BadRequestObjectResult>(response);
+            Assert.IsType<ErrorCollection>(((BadRequestObjectResult)response).Value);
+        }
+
         [Fact]
         public async Task PatchRelationshipsAsync_Calls_Service()
         {

From 52c8f64782800c158adabd7bd287196278c768d0 Mon Sep 17 00:00:00 2001
From: Simon Gent <simon.gent@gmail.com>
Date: Thu, 28 Jun 2018 09:03:33 +0100
Subject: [PATCH 204/227] bumped version no

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 75fc955402..cc337c28dc 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.3.2</VersionPrefix>
+    <VersionPrefix>2.3.3</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From 6f8bfe538837267fd4e57a38a12b080547dc349b Mon Sep 17 00:00:00 2001
From: Simon Gent <simon.gent@gmail.com>
Date: Thu, 28 Jun 2018 14:02:19 +0100
Subject: [PATCH 205/227] styling updates

---
 src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs | 6 ++++--
 src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs   | 3 ++-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
index 45f16e29ec..761e3cd957 100644
--- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
+++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
@@ -153,7 +153,8 @@ public virtual async Task<IActionResult> PostAsync([FromBody] T entity)
 
             if (!_jsonApiContext.Options.AllowClientGeneratedIds && !string.IsNullOrEmpty(entity.StringId))
                 return Forbidden();
-            if (!ModelState.IsValid) return BadRequest(ModelState.ConvertToErrorCollection());
+            if (!ModelState.IsValid)
+                return BadRequest(ModelState.ConvertToErrorCollection());
 
             entity = await _create.CreateAsync(entity);
 
@@ -166,7 +167,8 @@ public virtual async Task<IActionResult> PatchAsync(TId id, [FromBody] T entity)
 
             if (entity == null)
                 return UnprocessableEntity();
-            if (!ModelState.IsValid) return BadRequest(ModelState.ConvertToErrorCollection());
+            if (!ModelState.IsValid)
+                return BadRequest(ModelState.ConvertToErrorCollection());
 
             var updatedEntity = await _update.UpdateAsync(id, entity);
 
diff --git a/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs b/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs
index 0ccdc224eb..8eb0fc95f7 100644
--- a/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs
@@ -11,7 +11,8 @@ public static ErrorCollection ConvertToErrorCollection(this ModelStateDictionary
             ErrorCollection errors = new ErrorCollection();
             foreach (var entry in modelState)
             {
-                if (!entry.Value.Errors.Any()) continue;
+                if (!entry.Value.Errors.Any())
+                    continue;
                 foreach (var modelError in entry.Value.Errors)
                 {
                     errors.Errors.Add(new Error(400, entry.Key, modelError.ErrorMessage, modelError.Exception != null ? ErrorMeta.FromException(modelError.Exception) : null));

From 0051faacf8870e4fbc49f3ed7290d3a5150ff95f Mon Sep 17 00:00:00 2001
From: Simon Gent <simon.gent@gmail.com>
Date: Thu, 28 Jun 2018 16:26:20 +0100
Subject: [PATCH 206/227] added ValidateModelState as feature flag in options

---
 .../Configuration/JsonApiOptions.cs           | 10 ++++
 .../Controllers/BaseJsonApiController.cs      |  4 +-
 .../BaseJsonApiController_Tests.cs            | 51 +++++++++++++++++--
 3 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
index 502d678f0d..54fcf5afaf 100644
--- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
+++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs
@@ -125,6 +125,16 @@ public class JsonApiOptions
         /// </remarks>
         public bool EnableOperations { get; set; }
 
+        /// <summary>
+        /// Whether or not to validate model state.
+        /// </summary>
+        /// <example>
+        /// <code>
+        /// options.ValidateModelState = true;
+        /// </code>
+        /// </example>
+        public bool ValidateModelState { get; set; }
+
         [Obsolete("JsonContract resolver can now be set on SerializerSettings.")]
         public IContractResolver JsonContractResolver
         {
diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
index 761e3cd957..f4041e97d6 100644
--- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
+++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
@@ -153,7 +153,7 @@ public virtual async Task<IActionResult> PostAsync([FromBody] T entity)
 
             if (!_jsonApiContext.Options.AllowClientGeneratedIds && !string.IsNullOrEmpty(entity.StringId))
                 return Forbidden();
-            if (!ModelState.IsValid)
+            if (_jsonApiContext.Options.ValidateModelState && !ModelState.IsValid)
                 return BadRequest(ModelState.ConvertToErrorCollection());
 
             entity = await _create.CreateAsync(entity);
@@ -167,7 +167,7 @@ public virtual async Task<IActionResult> PatchAsync(TId id, [FromBody] T entity)
 
             if (entity == null)
                 return UnprocessableEntity();
-            if (!ModelState.IsValid)
+            if (_jsonApiContext.Options.ValidateModelState && !ModelState.IsValid)
                 return BadRequest(ModelState.ConvertToErrorCollection());
 
             var updatedEntity = await _update.UpdateAsync(id, entity);
diff --git a/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs b/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
index 4edfeddbe7..d2d3ac8319 100644
--- a/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
+++ b/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
@@ -146,6 +146,8 @@ public async Task PatchAsync_Calls_Service()
             const int id = 0;
             var resource = new Resource();
             var serviceMock = new Mock<IUpdateService<Resource>>();
+            _jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
+            _jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions());
             var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, update: serviceMock.Object);
 
             // act
@@ -157,12 +159,34 @@ public async Task PatchAsync_Calls_Service()
         }
 
         [Fact]
-        public async Task PatchAsync_ModelStateInvalid()
+        public async Task PatchAsync_ModelStateInvalid_ValidateModelStateDisbled()
+        {
+            // arrange
+            const int id = 0;
+            var resource = new Resource();
+            var serviceMock = new Mock<IUpdateService<Resource>>();
+            _jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
+            _jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions { ValidateModelState = false });
+            var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, update: serviceMock.Object);
+
+            // act
+            var response = await controller.PatchAsync(id, resource);
+
+            // assert
+            serviceMock.Verify(m => m.UpdateAsync(id, It.IsAny<Resource>()), Times.Once);
+            VerifyApplyContext();
+            Assert.IsNotType<BadRequestObjectResult>(response);
+        }
+
+        [Fact]
+        public async Task PatchAsync_ModelStateInvalid_ValidateModelStateEnabled()
         {
             // arrange
             const int id = 0;
             var resource = new Resource();
             var serviceMock = new Mock<IUpdateService<Resource>>();
+            _jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
+            _jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions{ValidateModelState = true});
             var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, update: serviceMock.Object);
             controller.ModelState.AddModelError("Id", "Failed Validation");
 
@@ -211,13 +235,34 @@ public async Task PostAsync_Calls_Service()
         }
 
         [Fact]
-        public async Task PostAsync_ModelStateInvalid()
+        public async Task PostAsync_ModelStateInvalid_ValidateModelStateDisabled()
         {
             // arrange
             var resource = new Resource();
             var serviceMock = new Mock<ICreateService<Resource>>();
             _jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
-            _jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions());
+            _jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions { ValidateModelState = false });
+            var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, create: serviceMock.Object);
+            serviceMock.Setup(m => m.CreateAsync(It.IsAny<Resource>())).ReturnsAsync(resource);
+            controller.ControllerContext = new Microsoft.AspNetCore.Mvc.ControllerContext { HttpContext = new DefaultHttpContext() };
+
+            // act
+            var response = await controller.PostAsync(resource);
+
+            // assert
+            serviceMock.Verify(m => m.CreateAsync(It.IsAny<Resource>()), Times.Once);
+            VerifyApplyContext();
+            Assert.IsNotType<BadRequestObjectResult>(response);
+        }
+
+        [Fact]
+        public async Task PostAsync_ModelStateInvalid_ValidateModelStateEnabled()
+        {
+            // arrange
+            var resource = new Resource();
+            var serviceMock = new Mock<ICreateService<Resource>>();
+            _jsonApiContextMock.Setup(a => a.ApplyContext<Resource>(It.IsAny<BaseJsonApiController<Resource>>())).Returns(_jsonApiContextMock.Object);
+            _jsonApiContextMock.SetupGet(a => a.Options).Returns(new JsonApiOptions { ValidateModelState = true });
             var controller = new BaseJsonApiController<Resource>(_jsonApiContextMock.Object, create: serviceMock.Object);
             controller.ModelState.AddModelError("Id", "Failed Validation");
 

From 29e1080483be870612c10bb3d462dccd51cb27a2 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 28 Jun 2018 19:13:39 -0700
Subject: [PATCH 207/227] propagate model state errors

---
 .../Controllers/BaseJsonApiController.cs      |  4 ++-
 .../Extensions/ModelStateExtensions.cs        | 13 +++++++---
 .../Formatters/JsonApiReader.cs               |  6 ++---
 .../Serialization/JsonApiDeSerializer.cs      | 13 ++++++++--
 test/UnitTests/Models/IdentifiableTests.cs    | 26 +++++++++++++++++++
 5 files changed, 51 insertions(+), 11 deletions(-)
 create mode 100644 test/UnitTests/Models/IdentifiableTests.cs

diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
index f4041e97d6..fd6ec8947a 100644
--- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
+++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs
@@ -146,13 +146,15 @@ public virtual async Task<IActionResult> GetRelationshipAsync(TId id, string rel
 
         public virtual async Task<IActionResult> PostAsync([FromBody] T entity)
         {
-            if (_create == null) throw Exceptions.UnSupportedRequestMethod;
+            if (_create == null)
+                throw Exceptions.UnSupportedRequestMethod;
 
             if (entity == null)
                 return UnprocessableEntity();
 
             if (!_jsonApiContext.Options.AllowClientGeneratedIds && !string.IsNullOrEmpty(entity.StringId))
                 return Forbidden();
+
             if (_jsonApiContext.Options.ValidateModelState && !ModelState.IsValid)
                 return BadRequest(ModelState.ConvertToErrorCollection());
 
diff --git a/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs b/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs
index 8eb0fc95f7..d67f7e66c4 100644
--- a/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs
@@ -8,17 +8,22 @@ public static class ModelStateExtensions
     {
         public static ErrorCollection ConvertToErrorCollection(this ModelStateDictionary modelState)
         {
-            ErrorCollection errors = new ErrorCollection();
+            ErrorCollection collection = new ErrorCollection();
             foreach (var entry in modelState)
             {
-                if (!entry.Value.Errors.Any())
+                if (entry.Value.Errors.Any() == false)
                     continue;
+
                 foreach (var modelError in entry.Value.Errors)
                 {
-                    errors.Errors.Add(new Error(400, entry.Key, modelError.ErrorMessage, modelError.Exception != null ? ErrorMeta.FromException(modelError.Exception) : null));
+                    if (modelError.Exception is JsonApiException jex)
+                        collection.Errors.AddRange(jex.GetError().Errors);
+                    else
+                        collection.Errors.Add(new Error(400, entry.Key, modelError.ErrorMessage, modelError.Exception != null ? ErrorMeta.FromException(modelError.Exception) : null));
                 }
             }
-            return errors;
+
+            return collection;
         }
     }
 }
diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs b/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs
index 204f3e0491..e10a3f31c2 100644
--- a/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs
+++ b/src/JsonApiDotNetCore/Formatters/JsonApiReader.cs
@@ -52,11 +52,9 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
                 context.ModelState.AddModelError(context.ModelName, ex, context.Metadata);
                 return InputFormatterResult.FailureAsync();
             }
-            catch (JsonApiException jex)
+            catch (JsonApiException)
             {
-                _logger?.LogError(new EventId(), jex, "An error occurred while de-serializing the payload");
-                context.ModelState.AddModelError(context.ModelName, jex, context.Metadata);
-                return InputFormatterResult.FailureAsync();
+                throw;
             }
         }
 
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index a1e3c76214..285923995d 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -57,6 +57,10 @@ public object Deserialize(string requestBody)
                 var entity = DocumentToObject(document.Data, document.Included);
                 return entity;
             }
+            catch (JsonApiException)
+            {
+                throw;
+            }
             catch (Exception e)
             {
                 throw new JsonApiException(400, "Failed to deserialize request body", e);
@@ -109,10 +113,15 @@ public List<TEntity> DeserializeList<TEntity>(string requestBody)
 
         public object DocumentToObject(DocumentData data, List<DocumentData> included = null)
         {
-            if (data == null) throw new JsonApiException(422, "Failed to deserialize document as json:api.");
+            if (data == null)
+                throw new JsonApiException(422, "Failed to deserialize document as json:api.");
 
             var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(data.Type?.ToString());
-            _jsonApiContext.RequestEntity = contextEntity;
+            _jsonApiContext.RequestEntity = contextEntity ?? throw new JsonApiException(400,
+                    message: $"This API does not contain a json:api resource named '{data.Type}'.",
+                    detail: "This resource is not registered on the ContextGraph. "
+                            + "If you are using Entity Framework, make sure the DbSet matches the expected resource name. "
+                            + "If you have manually registered the resource, check that the call to AddResource correctly sets the public name."); ;
 
             var entity = Activator.CreateInstance(contextEntity.EntityType);
 
diff --git a/test/UnitTests/Models/IdentifiableTests.cs b/test/UnitTests/Models/IdentifiableTests.cs
new file mode 100644
index 0000000000..778b1b485f
--- /dev/null
+++ b/test/UnitTests/Models/IdentifiableTests.cs
@@ -0,0 +1,26 @@
+using JsonApiDotNetCore.Models;
+using Xunit;
+
+namespace UnitTests.Models
+{
+    public class IdentifiableTests
+    {
+        [Fact]
+        public void Can_Set_StringId_To_Value_Type()
+        {
+            var resource = new IntId();
+            resource.StringId = "1";
+            Assert.Equal(1, resource.Id);
+        }
+
+        [Fact]
+        public void Setting_StringId_To_Null_Sets_Id_As_Default()
+        {
+            var resource = new IntId();
+            resource.StringId = null;
+            Assert.Equal(0, resource.Id);
+        }
+
+        private class IntId : Identifiable { }
+    }
+}

From 63598ab5dc515b6fc6298c954c456a77fe9091cc Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 28 Jun 2018 19:15:33 -0700
Subject: [PATCH 208/227] chore(csproj): bump package version

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index cc337c28dc..a212eecd70 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.3.3</VersionPrefix>
+    <VersionPrefix>2.3.4</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From 516b70a6c8162e1743320228f305000d0f8b299a Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 2 Jul 2018 10:12:16 -0700
Subject: [PATCH 209/227] feat(DocumentBuilder): allow for output attribute
 filtering

---
 .../Controllers/UsersController.cs            |  17 ++
 .../Data/AppDbContext.cs                      |   2 +-
 .../Migrations/20180327120810_initial.cs      |   2 -
 .../JsonApiDotNetCoreExample/Models/User.cs   |  10 ++
 .../Resources/UserResource.cs                 |  12 ++
 .../JsonApiDotNetCoreExample/Startup.cs       |   7 +-
 .../Controllers/ReportsController.cs          |   5 +-
 .../ReportsExample/Services/ReportService.cs  |   1 -
 .../Builders/ContextGraphBuilder.cs           |  12 +-
 .../Builders/DocumentBuilder.cs               |  28 +++-
 .../Builders/IDocumentBuilder.cs              |   6 +-
 .../Controllers/JsonApiCmdController.cs       |   1 -
 .../Controllers/JsonApiQueryController.cs     |   2 -
 .../DependencyInjection/ServiceLocator.cs     |  18 +++
 .../Extensions/DbContextExtensions.cs         |   1 -
 .../Internal/ContextEntity.cs                 |  29 ++++
 .../Internal/ContextGraph.cs                  |   4 +-
 .../Internal/Generics/GenericProcessor.cs     |   1 -
 .../Generics/GenericProcessorFactory.cs       |   1 -
 .../Internal/JsonApiRouteHandler.cs           |   1 -
 .../Internal/Query/AttrFilterQuery.cs         |   1 -
 .../Internal/Query/RelatedAttrFilterQuery.cs  |   2 -
 src/JsonApiDotNetCore/Models/AttrAttribute.cs |  26 ++-
 .../Models/ResourceDefinition.cs              | 107 +++++++++++++
 .../Serialization/JsonApiDeSerializer.cs      |  15 +-
 .../Serialization/JsonApiSerializer.cs        |   2 +-
 .../Operations/Processors/GetOpProcessor.cs   |   1 -
 .../NullValuedAttributeHandlingTests.cs       |   1 -
 .../Extensibility/RepositoryOverrideTests.cs  |   1 -
 .../Extensibility/RequestMetaTests.cs         |   1 -
 .../ResourceDefinitions/OutputAttrs_Tests.cs  | 148 ++++++++++++++++++
 .../Acceptance/Spec/AttributeFilterTests.cs   |   1 -
 .../Acceptance/Spec/AttributeSortTests.cs     |   1 -
 .../Acceptance/Spec/DocumentTests/Included.cs |   1 -
 .../Spec/FetchingRelationshipsTests.cs        |   3 +-
 .../Acceptance/Spec/PagingTests.cs            |   1 -
 .../Acceptance/TodoItemsControllerTests.cs    |   1 -
 .../Extensions/IQueryableExtensions.cs        |   1 -
 .../AuthorizedTodoItemsRepository.cs          |   1 -
 .../WebHostCollection.cs                      |   1 -
 .../Builders/ContextGraphBuilder_Tests.cs     |  11 +-
 .../DocumentBuilderBehaviour_Tests.cs         |   3 -
 .../Builders/DocumentBuilder_Tests.cs         | 120 +++++++++++++-
 .../BaseJsonApiController_Tests.cs            |   1 -
 .../JsonApiControllerMixin_Tests.cs           |   1 -
 .../Data/DefaultEntityRepository_Tests.cs     |   9 +-
 .../Models/ResourceDefinitionTests.cs         | 129 +++++++++++++++
 test/UnitTests/Services/QueryComposerTests.cs |   1 -
 48 files changed, 655 insertions(+), 96 deletions(-)
 create mode 100644 src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs
 create mode 100644 src/Examples/JsonApiDotNetCoreExample/Models/User.cs
 create mode 100644 src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs
 create mode 100644 src/JsonApiDotNetCore/DependencyInjection/ServiceLocator.cs
 create mode 100644 src/JsonApiDotNetCore/Models/ResourceDefinition.cs
 create mode 100644 test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/OutputAttrs_Tests.cs
 create mode 100644 test/UnitTests/Models/ResourceDefinitionTests.cs

diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs
new file mode 100644
index 0000000000..dbd144caa4
--- /dev/null
+++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs
@@ -0,0 +1,17 @@
+using JsonApiDotNetCore.Controllers;
+using JsonApiDotNetCore.Services;
+using JsonApiDotNetCoreExample.Models;
+using Microsoft.Extensions.Logging;
+
+namespace JsonApiDotNetCoreExample.Controllers
+{
+    public class UsersController : JsonApiController<User>
+    {
+        public UsersController(
+            IJsonApiContext jsonApiContext,
+            IResourceService<User> resourceService,
+            ILoggerFactory loggerFactory) 
+            : base(jsonApiContext, resourceService, loggerFactory)
+        { }
+    }
+}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
index 4b9a40f7fd..6f50f9aa5b 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
@@ -37,7 +37,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
 
         public DbSet<Article> Articles { get; set; }
         public DbSet<Author> Authors { get; set; }
-
         public DbSet<NonJsonApiResource> NonJsonApiResources { get; set; }
+        public DbSet<User> Users { get; set; }
     }
 }
diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
index cc696f54bf..ffbf105255 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs
@@ -1,7 +1,5 @@
-using Microsoft.EntityFrameworkCore.Metadata;
 using Microsoft.EntityFrameworkCore.Migrations;
 using System;
-using System.Collections.Generic;
 using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
 
 namespace JsonApiDotNetCoreExample.Migrations
diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/User.cs b/src/Examples/JsonApiDotNetCoreExample/Models/User.cs
new file mode 100644
index 0000000000..3b66f0dbb2
--- /dev/null
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/User.cs
@@ -0,0 +1,10 @@
+using JsonApiDotNetCore.Models;
+
+namespace JsonApiDotNetCoreExample.Models
+{
+    public class User : Identifiable
+    {
+        [Attr("username")] public string Username { get; set; }
+        [Attr("password")] public string Password { get; set; }
+    }
+}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs b/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs
new file mode 100644
index 0000000000..030bc4eaa4
--- /dev/null
+++ b/src/Examples/JsonApiDotNetCoreExample/Resources/UserResource.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCoreExample.Models;
+
+namespace JsonApiDotNetCoreExample.Resources
+{
+    public class UserResource : ResourceDefinition<User>
+    {
+        protected override List<AttrAttribute> OutputAttrs()
+            => Remove(user => user.Password);
+    }
+}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Startup.cs b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
index 2c7574e1a2..ec1bdc544c 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Startup.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
@@ -7,6 +7,9 @@
 using Microsoft.EntityFrameworkCore;
 using JsonApiDotNetCore.Extensions;
 using System;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCoreExample.Resources;
+using JsonApiDotNetCoreExample.Models;
 
 namespace JsonApiDotNetCoreExample
 {
@@ -38,7 +41,9 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
                     options.Namespace = "api/v1";
                     options.DefaultPageSize = 5;
                     options.IncludeTotalRecordCount = true;
-                });
+                })
+                // TODO: this should be handled via auto-discovery
+                .AddScoped<ResourceDefinition<User>, UserResource>();
 
             var provider = services.BuildServiceProvider();
             var appContext = provider.GetRequiredService<AppDbContext>();
diff --git a/src/Examples/ReportsExample/Controllers/ReportsController.cs b/src/Examples/ReportsExample/Controllers/ReportsController.cs
index 523ad417bd..6f431d9291 100644
--- a/src/Examples/ReportsExample/Controllers/ReportsController.cs
+++ b/src/Examples/ReportsExample/Controllers/ReportsController.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
 using Microsoft.AspNetCore.Mvc;
 using JsonApiDotNetCore.Controllers;
 using JsonApiDotNetCore.Services;
diff --git a/src/Examples/ReportsExample/Services/ReportService.cs b/src/Examples/ReportsExample/Services/ReportService.cs
index 7baffc6174..9e5348a612 100644
--- a/src/Examples/ReportsExample/Services/ReportService.cs
+++ b/src/Examples/ReportsExample/Services/ReportService.cs
@@ -1,4 +1,3 @@
-using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Services;
diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index 73e355b2de..080c0a6bb7 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -59,7 +59,6 @@ public IContextGraph Build()
             _entities.ForEach(e => e.Links = GetLinkFlags(e.EntityType));
 
             var graph = new ContextGraph(_entities, _usesDbContext, _validationResults);
-
             return graph;
         }
 
@@ -83,7 +82,8 @@ public IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeNam
             EntityType = entityType,
             IdentityType = idType,
             Attributes = GetAttributes(entityType),
-            Relationships = GetRelationships(entityType)
+            Relationships = GetRelationships(entityType),
+            ResourceType = GetResourceDefinitionType(entityType)
         };
 
         private Link GetLinkFlags(Type entityType)
@@ -104,8 +104,12 @@ protected virtual List<AttrAttribute> GetAttributes(Type entityType)
             foreach (var prop in properties)
             {
                 var attribute = (AttrAttribute)prop.GetCustomAttribute(typeof(AttrAttribute));
-                if (attribute == null) continue;
+                if (attribute == null)
+                    continue;
+
                 attribute.InternalAttributeName = prop.Name;
+                attribute.PropertyInfo = prop;
+
                 attributes.Add(attribute);
             }
             return attributes;
@@ -136,6 +140,8 @@ protected virtual Type GetRelationshipType(RelationshipAttribute relation, Prope
                 return prop.PropertyType;
         }
 
+        private Type GetResourceDefinitionType(Type entityType) => typeof(ResourceDefinition<>).MakeGenericType(entityType);
+
         public IContextGraphBuilder AddDbContext<T>() where T : DbContext
         {
             _usesDbContext = true;
diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
index 9f86a57945..c6f5f999b4 100644
--- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -14,22 +15,29 @@ public class DocumentBuilder : IDocumentBuilder
         private readonly IContextGraph _contextGraph;
         private readonly IRequestMeta _requestMeta;
         private readonly DocumentBuilderOptions _documentBuilderOptions;
+        private readonly IScopedServiceProvider _scopedServiceProvider;
 
-        public DocumentBuilder(IJsonApiContext jsonApiContext, IRequestMeta requestMeta = null, IDocumentBuilderOptionsProvider documentBuilderOptionsProvider = null)
+        public DocumentBuilder(
+            IJsonApiContext jsonApiContext, 
+            IRequestMeta requestMeta = null, 
+            IDocumentBuilderOptionsProvider documentBuilderOptionsProvider = null,
+            IScopedServiceProvider scopedServiceProvider = null)
         {
             _jsonApiContext = jsonApiContext;
             _contextGraph = jsonApiContext.ContextGraph;
             _requestMeta = requestMeta;
-            _documentBuilderOptions = documentBuilderOptionsProvider?.GetDocumentBuilderOptions() ?? new DocumentBuilderOptions(); ;
+            _documentBuilderOptions = documentBuilderOptionsProvider?.GetDocumentBuilderOptions() ?? new DocumentBuilderOptions();
+            _scopedServiceProvider = scopedServiceProvider;
         }
 
         public Document Build(IIdentifiable entity)
         {
             var contextEntity = _contextGraph.GetContextEntity(entity.GetType());
 
+            var resourceDefinition = _scopedServiceProvider?.GetService(contextEntity.ResourceType) as IResourceDefinition;
             var document = new Document
             {
-                Data = GetData(contextEntity, entity),
+                Data = GetData(contextEntity, entity, resourceDefinition),
                 Meta = GetMeta(entity)
             };
 
@@ -44,8 +52,8 @@ public Document Build(IIdentifiable entity)
         public Documents Build(IEnumerable<IIdentifiable> entities)
         {
             var entityType = entities.GetElementType();
-
             var contextEntity = _contextGraph.GetContextEntity(entityType);
+            var resourceDefinition = _scopedServiceProvider?.GetService(contextEntity.ResourceType) as IResourceDefinition;
 
             var enumeratedEntities = entities as IList<IIdentifiable> ?? entities.ToList();
             var documents = new Documents
@@ -59,7 +67,7 @@ public Documents Build(IEnumerable<IIdentifiable> entities)
 
             foreach (var entity in enumeratedEntities)
             {
-                documents.Data.Add(GetData(contextEntity, entity));
+                documents.Data.Add(GetData(contextEntity, entity, resourceDefinition));
                 documents.Included = AppendIncludedObject(documents.Included, contextEntity, entity);
             }
 
@@ -98,7 +106,11 @@ private List<DocumentData> AppendIncludedObject(List<DocumentData> includedObjec
             return includedObject;
         }
 
+        [Obsolete("You should specify an IResourceDefinition implementation using the GetData/3 overload.")]
         public DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
+            => GetData(contextEntity, entity, resourceDefinition: null);
+
+        public DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity, IResourceDefinition resourceDefinition = null)
         {
             var data = new DocumentData
             {
@@ -111,7 +123,8 @@ public DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity)
 
             data.Attributes = new Dictionary<string, object>();
 
-            contextEntity.Attributes.ForEach(attr =>
+            var resourceAttributes = resourceDefinition?.GetOutputAttrs(entity) ?? contextEntity.Attributes;
+            resourceAttributes.ForEach(attr =>
             {
                 var attributeValue = attr.GetValue(entity);
                 if (ShouldIncludeAttribute(attr, attributeValue))
@@ -219,8 +232,9 @@ private DocumentData GetIncludedEntity(IIdentifiable entity)
             if (entity == null) return null;
 
             var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(entity.GetType());
+            var resourceDefinition = _scopedServiceProvider.GetService(contextEntity.ResourceType) as IResourceDefinition;
 
-            var data = GetData(contextEntity, entity);
+            var data = GetData(contextEntity, entity, resourceDefinition);
 
             data.Attributes = new Dictionary<string, object>();
 
diff --git a/src/JsonApiDotNetCore/Builders/IDocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/IDocumentBuilder.cs
index 4fbc8df01b..dccd6f753a 100644
--- a/src/JsonApiDotNetCore/Builders/IDocumentBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/IDocumentBuilder.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections.Generic;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
@@ -8,6 +9,9 @@ public interface IDocumentBuilder
     {
         Document Build(IIdentifiable entity);
         Documents Build(IEnumerable<IIdentifiable> entities);
+
+        [Obsolete("You should specify an IResourceDefinition implementation using the GetData/3 overload.")]
         DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity);
+        DocumentData GetData(ContextEntity contextEntity, IIdentifiable entity, IResourceDefinition resourceDefinition = null);
     }
-}
\ No newline at end of file
+}
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiCmdController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiCmdController.cs
index 20e5445ebb..82c0fe40c4 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiCmdController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiCmdController.cs
@@ -3,7 +3,6 @@
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
 
 namespace JsonApiDotNetCore.Controllers
 {
diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs
index 3e78bc4f8f..5211e5fa3b 100644
--- a/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs
+++ b/src/JsonApiDotNetCore/Controllers/JsonApiQueryController.cs
@@ -1,9 +1,7 @@
-using System.Collections.Generic;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
 
 namespace JsonApiDotNetCore.Controllers
 {
diff --git a/src/JsonApiDotNetCore/DependencyInjection/ServiceLocator.cs b/src/JsonApiDotNetCore/DependencyInjection/ServiceLocator.cs
new file mode 100644
index 0000000000..31164ee3b9
--- /dev/null
+++ b/src/JsonApiDotNetCore/DependencyInjection/ServiceLocator.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Threading;
+
+namespace JsonApiDotNetCore.DependencyInjection
+{
+    internal class ServiceLocator
+    {
+        public static AsyncLocal<IServiceProvider> _scopedProvider = new AsyncLocal<IServiceProvider>();
+        public static void Initialize(IServiceProvider serviceProvider) => _scopedProvider.Value = serviceProvider;
+        
+        public static object GetService(Type type)
+            => _scopedProvider.Value != null
+                ? _scopedProvider.Value.GetService(type)
+                : throw new InvalidOperationException(
+                    $"Service locator has not been initialized for the current asynchronous flow. Call {nameof(Initialize)} first."
+                );
+    }
+}
diff --git a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
index 2756524dce..9176474548 100644
--- a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Linq;
-using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
 
diff --git a/src/JsonApiDotNetCore/Internal/ContextEntity.cs b/src/JsonApiDotNetCore/Internal/ContextEntity.cs
index ff539b79ea..1e15a9c6bc 100644
--- a/src/JsonApiDotNetCore/Internal/ContextEntity.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextEntity.cs
@@ -6,11 +6,40 @@ namespace JsonApiDotNetCore.Internal
 {
     public class ContextEntity
     {
+        /// <summary>
+        /// The exposed resource name
+        /// </summary>
         public string EntityName { get; set; }
+
+        /// <summary>
+        /// The data model type
+        /// </summary>
         public Type EntityType { get; set; }
+
+        /// <summary>
+        /// The identity member type
+        /// </summary>
         public Type IdentityType { get; set; }
+
+        /// <summary>
+        /// The concrete <see cref="ResourceDefinition{T}"/> type.
+        /// We store this so that we don't need to re-compute the generic type.
+        /// </summary>
+        public Type ResourceType { get; set; }
+
+        /// <summary>
+        /// Exposed resource attributes
+        /// </summary>
         public List<AttrAttribute> Attributes { get; set; }
+
+        /// <summary>
+        /// Exposed resource relationships
+        /// </summary>
         public List<RelationshipAttribute> Relationships { get; set; }
+
+        /// <summary>
+        /// Links to include in resource responses
+        /// </summary>
         public Link Links { get; set; } = Link.All;
     }
 }
diff --git a/src/JsonApiDotNetCore/Internal/ContextGraph.cs b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
index c27a01b7d8..9c62ae4d94 100644
--- a/src/JsonApiDotNetCore/Internal/ContextGraph.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextGraph.cs
@@ -17,14 +17,15 @@ public class ContextGraph : IContextGraph
     {
         internal List<ContextEntity> Entities { get; }
         internal List<ValidationResult> ValidationResults { get; }
+        internal static IContextGraph Instance { get; set; }
 
         public ContextGraph() { }
-
         public ContextGraph(List<ContextEntity> entities, bool usesDbContext)
         {
             Entities = entities;
             UsesDbContext = usesDbContext;
             ValidationResults = new List<ValidationResult>();
+            Instance = this;
         }
 
         // eventually, this is the planned public constructor
@@ -36,6 +37,7 @@ internal ContextGraph(List<ContextEntity> entities, bool usesDbContext, List<Val
             Entities = entities;
             UsesDbContext = usesDbContext;
             ValidationResults = validationResults;
+            Instance = this;
         }
 
         public bool UsesDbContext { get; }
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
index 1aa6610790..0a56fdfd4a 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessor.cs
@@ -2,7 +2,6 @@
 using System.Linq;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Data;
-using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
 
diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
index 08cba58dd1..5baa9615bb 100644
--- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
+++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs
@@ -1,5 +1,4 @@
 using JsonApiDotNetCore.Services;
-using Microsoft.AspNetCore.Http;
 using System;
 
 namespace JsonApiDotNetCore.Internal.Generics
diff --git a/src/JsonApiDotNetCore/Internal/JsonApiRouteHandler.cs b/src/JsonApiDotNetCore/Internal/JsonApiRouteHandler.cs
index 6675fc2879..132f8d2042 100644
--- a/src/JsonApiDotNetCore/Internal/JsonApiRouteHandler.cs
+++ b/src/JsonApiDotNetCore/Internal/JsonApiRouteHandler.cs
@@ -4,7 +4,6 @@
 using JsonApiDotNetCore.Extensions;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.Mvc.Infrastructure;
-using Microsoft.AspNetCore.Mvc.Internal;
 using Microsoft.AspNetCore.Routing;
 
 namespace JsonApiDotNetCore.Internal
diff --git a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
index 59bb3f0f83..a914fea3a7 100644
--- a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs
@@ -1,4 +1,3 @@
-using System;
 using System.Linq;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
index d567de200a..9b117c0913 100644
--- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
+++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs
@@ -1,6 +1,4 @@
-using System;
 using System.Linq;
-using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
 
diff --git a/src/JsonApiDotNetCore/Models/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
index f63d48ab70..017cf72118 100644
--- a/src/JsonApiDotNetCore/Models/AttrAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Reflection;
 using JsonApiDotNetCore.Internal;
 
 namespace JsonApiDotNetCore.Models
@@ -69,34 +70,25 @@ public AttrAttribute(string publicName, string internalName, bool isImmutable =
         /// </summary>
         public bool IsSortable { get; }
 
+        /// <summary>
+        /// The member property info
+        /// </summary>
+        internal PropertyInfo PropertyInfo { get; set; }
+
         /// <summary>
         /// Get the value of the attribute for the given object.
         /// Returns null if the attribute does not belong to the
         /// provided object.
         /// </summary>
-        public object GetValue(object entity)
-        {
-            return entity
-                .GetType()
-                .GetProperty(InternalAttributeName)
-                ?.GetValue(entity);
-        }
+        public object GetValue(object entity) => PropertyInfo.GetValue(entity);
 
         /// <summary>
         /// Sets the value of the attribute on the given object.
         /// </summary>
         public void SetValue(object entity, object newValue)
         {
-            var propertyInfo = entity
-                .GetType()
-                .GetProperty(InternalAttributeName);
-
-            if (propertyInfo != null)
-            {
-                var convertedValue = TypeHelper.ConvertType(newValue, propertyInfo.PropertyType);
-
-                propertyInfo.SetValue(entity, convertedValue);
-            }
+            var convertedValue = TypeHelper.ConvertType(newValue, PropertyInfo.PropertyType);
+            PropertyInfo.SetValue(entity, convertedValue);
         }
 
         /// <summary>
diff --git a/src/JsonApiDotNetCore/Models/ResourceDefinition.cs b/src/JsonApiDotNetCore/Models/ResourceDefinition.cs
new file mode 100644
index 0000000000..03ac62390b
--- /dev/null
+++ b/src/JsonApiDotNetCore/Models/ResourceDefinition.cs
@@ -0,0 +1,107 @@
+using JsonApiDotNetCore.Internal;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace JsonApiDotNetCore.Models
+{
+    public interface IResourceDefinition
+    {
+        List<AttrAttribute> GetOutputAttrs(object instance);
+    }
+
+    /// <summary>
+    /// A scoped service used to...
+    /// </summary>
+    /// <typeparam name="T">The resource type</typeparam>
+    public class ResourceDefinition<T> : IResourceDefinition where T : class, IIdentifiable
+    {
+        private readonly IContextGraph _graph;
+        private readonly ContextEntity _contextEntity;
+        internal readonly bool _instanceAttrsAreSpecified;
+
+        private bool _requestCachedAttrsHaveBeenLoaded = false;
+        private List<AttrAttribute> _requestCachedAttrs;
+
+        public ResourceDefinition()
+        {
+            _graph = ContextGraph.Instance;
+            _contextEntity = ContextGraph.Instance.GetContextEntity(typeof(T));
+            _instanceAttrsAreSpecified = InstanceOutputAttrsAreSpecified();
+        }
+
+        private bool InstanceOutputAttrsAreSpecified()
+        {
+            var derivedType = GetType();
+            var methods = derivedType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
+            var instanceMethod = methods
+                .Where(m =>
+                   m.Name == nameof(OutputAttrs)
+                   && m.GetParameters()
+                        .FirstOrDefault()
+                        ?.ParameterType == typeof(T))
+                .FirstOrDefault();
+            var declaringType = instanceMethod?.DeclaringType;
+            return declaringType == derivedType;
+        }
+        
+        // TODO: need to investigate options for caching these
+        protected List<AttrAttribute> Remove(Expression<Func<T, dynamic>> filter, List<AttrAttribute> from = null)
+        {
+            from = from ?? _contextEntity.Attributes;
+
+            // model => model.Attribute
+            if (filter.Body is MemberExpression memberExpression)
+                return _contextEntity.Attributes
+                        .Where(a => a.PropertyInfo.Name != memberExpression.Member.Name)
+                        .ToList();
+
+            // model => new { model.Attribute1, model.Attribute2 }
+            if (filter.Body is NewExpression newExpression)
+            {
+                var attributes = new List<AttrAttribute>();
+                foreach (var attr in _contextEntity.Attributes)
+                    if (newExpression.Members.Any(m => m.Name == attr.PropertyInfo.Name) == false)
+                        attributes.Add(attr);                 
+
+                return attributes;
+            }
+
+            throw new JsonApiException(500,
+                message: $"The expression returned by '{filter}' for '{GetType()}' is of type {filter.Body.GetType()}"
+                        + " and cannot be used to select resource attributes. ",
+                detail: "The type must be a NewExpression. Example: article => new { article.Author }; ");
+        }
+
+        /// <summary>
+        /// Called once per filtered resource in request.
+        /// </summary>
+        protected virtual List<AttrAttribute> OutputAttrs() => _contextEntity.Attributes;
+
+        /// <summary>
+        /// Called for every instance of a resource
+        /// </summary>
+        protected virtual List<AttrAttribute> OutputAttrs(T instance) => _contextEntity.Attributes;
+
+        public List<AttrAttribute> GetOutputAttrs(object instance)
+            => _instanceAttrsAreSpecified == false
+                ? GetOutputAttrs()
+                : OutputAttrs(instance as T);
+
+        private List<AttrAttribute> GetOutputAttrs()
+        {
+            if (_requestCachedAttrsHaveBeenLoaded == false)
+            {
+                _requestCachedAttrs = OutputAttrs();
+                // the reason we don't just check for null is because we
+                // guarantee that OutputAttrs will be called once per
+                // request and null is a valid return value
+                _requestCachedAttrsHaveBeenLoaded = true;
+            }
+
+            return _requestCachedAttrs;
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 285923995d..0c3b7217fe 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -124,7 +124,7 @@ public object DocumentToObject(DocumentData data, List<DocumentData> included =
                             + "If you have manually registered the resource, check that the call to AddResource correctly sets the public name."); ;
 
             var entity = Activator.CreateInstance(contextEntity.EntityType);
-
+            
             entity = SetEntityAttributes(entity, contextEntity, data.Attributes);
             entity = SetRelationships(entity, contextEntity, data.Relationships, included);
 
@@ -141,20 +141,13 @@ private object SetEntityAttributes(
         {
             if (attributeValues == null || attributeValues.Count == 0)
                 return entity;
-
-            var entityProperties = entity.GetType().GetProperties();
-
+            
             foreach (var attr in contextEntity.Attributes)
             {
-                var entityProperty = entityProperties.FirstOrDefault(p => p.Name == attr.InternalAttributeName);
-
-                if (entityProperty == null)
-                    throw new ArgumentException($"{contextEntity.EntityType.Name} does not contain an attribute named {attr.InternalAttributeName}", nameof(entity));
-
                 if (attributeValues.TryGetValue(attr.PublicAttributeName, out object newValue))
                 {
-                    var convertedValue = ConvertAttrValue(newValue, entityProperty.PropertyType);
-                    entityProperty.SetValue(entity, convertedValue);
+                    var convertedValue = ConvertAttrValue(newValue, attr.PropertyInfo.PropertyType);
+                    attr.PropertyInfo.SetValue(entity, convertedValue);
 
                     if (attr.IsImmutable == false)
                         _jsonApiContext.AttributesToUpdate[attr] = convertedValue;
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
index 500101cc62..a784554f58 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs
@@ -13,7 +13,7 @@ public class JsonApiSerializer : IJsonApiSerializer
         private readonly IDocumentBuilder _documentBuilder;
         private readonly ILogger<JsonApiSerializer> _logger;
         private readonly IJsonApiContext _jsonApiContext;
-
+        
         public JsonApiSerializer(
             IJsonApiContext jsonApiContext,
             IDocumentBuilder documentBuilder)
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
index d8793d016c..a3737dd57d 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
@@ -1,4 +1,3 @@
-using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs
index 7942ffd919..05c348a553 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs
@@ -3,7 +3,6 @@
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Models;
-using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using Newtonsoft.Json;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
index 09a2791048..95ea814a5d 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
@@ -3,7 +3,6 @@
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
-using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using JsonApiDotNetCoreExampleTests.Services;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs
index 2397bb5529..4f9198619a 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs
@@ -5,7 +5,6 @@
 using Microsoft.AspNetCore.TestHost;
 using Xunit;
 using JsonApiDotNetCoreExample.Models;
-using JsonApiDotNetCoreExample;
 using Newtonsoft.Json;
 using JsonApiDotNetCore.Models;
 using System.Collections;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/OutputAttrs_Tests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/OutputAttrs_Tests.cs
new file mode 100644
index 0000000000..c5a6c054a4
--- /dev/null
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/ResourceDefinitions/OutputAttrs_Tests.cs
@@ -0,0 +1,148 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using Bogus;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Serialization;
+using JsonApiDotNetCoreExample.Data;
+using JsonApiDotNetCoreExample.Models;
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
+using Xunit;
+
+namespace JsonApiDotNetCoreExampleTests.Acceptance
+{
+    [Collection("WebHostCollection")]
+    public class OutputAttrs_Tests
+    {
+        private TestFixture<TestStartup> _fixture;
+        private AppDbContext _context;
+        private Faker<User> _userFaker;
+
+        public OutputAttrs_Tests(TestFixture<TestStartup> fixture)
+        {
+            _fixture = fixture;
+            _context = fixture.GetService<AppDbContext>();
+            _userFaker = new Faker<User>()
+                .RuleFor(u => u.Username, f => f.Internet.UserName())
+                .RuleFor(u => u.Password, f => f.Internet.Password());
+        }
+
+        [Fact]
+        public async Task Password_Is_Not_Included_In_Response_Payload()
+        {
+            // Arrange
+            var user = _userFaker.Generate();
+            _context.Users.Add(user);
+            _context.SaveChanges();
+
+            var httpMethod = new HttpMethod("GET");
+            var route = $"/api/v1/users/{user.Id}";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            // Act
+            var response = await _fixture.Client.SendAsync(request);
+
+            // Assert
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            var body = await response.Content.ReadAsStringAsync();
+            var document = JsonConvert.DeserializeObject<Document>(body);
+            Assert.False(document.Data.Attributes.ContainsKey("password"));
+        }
+
+        [Fact]
+        public async Task Can_Create_User_With_Password()
+        {
+            // Arrange
+            var user = _userFaker.Generate();
+            var content = new
+            {
+                data = new
+                {
+                    type = "users",
+                    attributes = new Dictionary<string, object>()
+                    {
+                        { "username", user.Username },
+                        { "password", user.Password },
+                    }
+                }
+            };
+
+            var httpMethod = new HttpMethod("POST");
+            var route = $"/api/v1/users";
+
+            var request = new HttpRequestMessage(httpMethod, route);
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await _fixture.Client.SendAsync(request);
+
+            // Assert
+            Assert.Equal(HttpStatusCode.Created, response.StatusCode);
+
+            // response assertions
+            var body = await response.Content.ReadAsStringAsync();
+            var deserializedBody = (User)_fixture.GetService<IJsonApiDeSerializer>().Deserialize(body);
+            var document = JsonConvert.DeserializeObject<Document>(body);
+            Assert.False(document.Data.Attributes.ContainsKey("password"));
+            Assert.Equal(user.Username, document.Data.Attributes["username"]);
+
+            // db assertions
+            var dbUser = await _context.Users.FindAsync(deserializedBody.Id);
+            Assert.Equal(user.Username, dbUser.Username);
+            Assert.Equal(user.Password, dbUser.Password);
+        }
+
+        [Fact]
+        public async Task Can_Update_User_Password()
+        {
+            // Arrange
+            var user = _userFaker.Generate();
+            _context.Users.Add(user);
+            _context.SaveChanges();
+
+            var newPassword = _userFaker.Generate().Password;
+
+            var content = new
+            {
+                data = new
+                {
+                    type = "users",
+                    id = user.Id,
+                    attributes = new Dictionary<string, object>()
+                    {
+                        { "password", newPassword },
+                    }
+                }
+            };
+
+            var httpMethod = new HttpMethod("PATCH");
+            var route = $"/api/v1/users/{user.Id}";
+
+            var request = new HttpRequestMessage(httpMethod, route);
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await _fixture.Client.SendAsync(request);
+
+            // Assert
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+
+            // response assertions
+            var body = await response.Content.ReadAsStringAsync();
+            var deserializedBody = (User)_fixture.GetService<IJsonApiDeSerializer>().Deserialize(body);
+            var document = JsonConvert.DeserializeObject<Document>(body);
+            Assert.False(document.Data.Attributes.ContainsKey("password"));
+            Assert.Equal(user.Username, document.Data.Attributes["username"]);
+
+            // db assertions
+            var dbUser = _context.Users.AsNoTracking().Single(u => u.Id == user.Id);
+            Assert.Equal(newPassword, dbUser.Password);
+        }
+    }
+}
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
index b928df4ada..9e154f9b47 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs
@@ -9,7 +9,6 @@
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
-using Microsoft.EntityFrameworkCore;
 using Newtonsoft.Json;
 using Xunit;
 using Person = JsonApiDotNetCoreExample.Models.Person;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs
index 6de3293596..4aef3817fe 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs
@@ -1,7 +1,6 @@
 using System.Net;
 using System.Net.Http;
 using System.Threading.Tasks;
-using JsonApiDotNetCoreExample;
 using Xunit;
 
 namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
index 25f81fb66c..cfe842616b 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs
@@ -1,4 +1,3 @@
-using System;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
index 621cb8e349..9c9ea29ccb 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs
@@ -1,5 +1,4 @@
-using System.Linq;
-using System.Net;
+using System.Net;
 using System.Net.Http;
 using System.Threading.Tasks;
 using Bogus;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
index 2d77982e62..0667b51756 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs
@@ -5,7 +5,6 @@
 using Bogus;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Serialization;
-using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExample.Models;
 using Xunit;
 using Person = JsonApiDotNetCoreExample.Models.Person;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
index 672492df16..cf1ea6de96 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
@@ -7,7 +7,6 @@
 using Bogus;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
-using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using Newtonsoft.Json;
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
index a7bfb95b9d..9298d93a05 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs
@@ -5,7 +5,6 @@
 using Microsoft.EntityFrameworkCore.Query;
 using Microsoft.EntityFrameworkCore.Query.Internal;
 using Microsoft.EntityFrameworkCore.Storage;
-using Remotion.Linq.Parsing.Structure;
 using Database = Microsoft.EntityFrameworkCore.Storage.Database;
 
 namespace JsonApiDotNetCoreExampleTests.Helpers.Extensions
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
index 32cb24cdcf..4ce5da35d8 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
@@ -1,7 +1,6 @@
 using System.Linq;
 using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Services;
-using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
 using JsonApiDotNetCoreExampleTests.Services;
 using Microsoft.Extensions.Logging;
diff --git a/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs b/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
index 960b7c1e46..561d86bbb0 100644
--- a/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
+++ b/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs
@@ -1,4 +1,3 @@
-using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExampleTests.Acceptance;
 using Xunit;
 
diff --git a/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs b/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs
index 8bcef5e4dd..d5207fb6ef 100644
--- a/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs
+++ b/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs
@@ -1,10 +1,8 @@
-using System;
 using JsonApiDotNetCore.Extensions;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection;
-using Moq;
 using Xunit;
 
 namespace UnitTests
@@ -33,10 +31,11 @@ public void Can_Build_ContextGraph_Using_Builder()
 
             // assert
             var contextGraph = container.GetRequiredService<IContextGraph>();
-            var dbResource = contextGraph.GetContextEntity("db-resources").EntityType;
-            var nonDbResource = contextGraph.GetContextEntity("non-db-resources").EntityType;
-            Assert.Equal(typeof(DbResource), dbResource);
-            Assert.Equal(typeof(NonDbResource), nonDbResource);
+            var dbResource = contextGraph.GetContextEntity("db-resources");
+            var nonDbResource = contextGraph.GetContextEntity("non-db-resources");
+            Assert.Equal(typeof(DbResource), dbResource.EntityType);
+            Assert.Equal(typeof(NonDbResource), nonDbResource.EntityType);
+            Assert.Equal(typeof(ResourceDefinition<NonDbResource>), nonDbResource.ResourceType);
         }
     }
 }
diff --git a/test/UnitTests/Builders/DocumentBuilderBehaviour_Tests.cs b/test/UnitTests/Builders/DocumentBuilderBehaviour_Tests.cs
index 333950f95f..3c5e2e5147 100644
--- a/test/UnitTests/Builders/DocumentBuilderBehaviour_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilderBehaviour_Tests.cs
@@ -1,6 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
 using JsonApiDotNetCore.Builders;
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Services;
diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
index 84c1f3f5c7..868ef698ee 100644
--- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs
+++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs
@@ -5,6 +5,7 @@
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
+using Microsoft.Extensions.DependencyInjection;
 using Moq;
 using Xunit;
 
@@ -154,7 +155,7 @@ public void Related_Data_Included_In_Relationships_By_Default()
         }
 
         [Fact]
-        public void IndependentIdentifier__Included_In_HasOne_Relationships_By_Default()
+        public void IndependentIdentifier_Included_In_HasOne_Relationships_By_Default()
         {
             // arrange
             const string relatedTypeName = "related-models";
@@ -204,7 +205,6 @@ public void Build_Can_Build_CustomIEnumerables()
             Assert.Single(documents.Data);
         }
 
-
         [Theory]
         [InlineData(null, null, true)]
         [InlineData(false, null, true)]
@@ -212,7 +212,8 @@ public void Build_Can_Build_CustomIEnumerables()
         [InlineData(null, "foo", true)]
         [InlineData(false, "foo", true)]
         [InlineData(true, "foo", true)]
-        public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
+        public void DocumentBuilderOptions(
+            bool? omitNullValuedAttributes,
             string attributeValue,
             bool resultContainsAttribute)
         {
@@ -230,12 +231,11 @@ public void DocumentBuilderOptions(bool? omitNullValuedAttributes,
 
         private class Model : Identifiable
         {
+            [Attr("StringProperty")] public string StringProperty { get; set; }
+
             [HasOne("related-model", Link.None)]
             public RelatedModel RelatedModel { get; set; }
             public int RelatedModelId { get; set; }
-            [Attr("StringProperty")]
-            public string StringProperty { get; set; }
-
         }
 
         private class RelatedModel : Identifiable
@@ -263,5 +263,113 @@ IEnumerator IEnumerable.GetEnumerator()
                 return models.GetEnumerator();
             }
         }
+
+        [Fact]
+        public void Build_Will_Use_Resource_If_Defined_For_Multiple_Documents()
+        {
+            var entities = new[] { new User() };
+            var contextGraph = new ContextGraphBuilder()
+                    .AddResource<User>("user")
+                    .Build();
+            _jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+
+            var scopedServiceProvider = new TestScopedServiceProvider(
+                new ServiceCollection()
+                    .AddScoped<ResourceDefinition<User>, UserResource>()
+                    .BuildServiceProvider());
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, scopedServiceProvider: scopedServiceProvider);
+
+            var documents = documentBuilder.Build(entities);
+
+            Assert.Single(documents.Data);
+            Assert.False(documents.Data[0].Attributes.ContainsKey("password"));
+            Assert.True(documents.Data[0].Attributes.ContainsKey("username"));
+        }
+
+        [Fact]
+        public void Build_Will_Use_Resource_If_Defined_For_Single_Document()
+        {
+            var entity = new User();
+            var contextGraph = new ContextGraphBuilder()
+                    .AddResource<User>("user")
+                    .Build();
+            _jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+
+            var scopedServiceProvider = new TestScopedServiceProvider(
+                new ServiceCollection()
+                    .AddScoped<ResourceDefinition<User>, UserResource>()
+                    .BuildServiceProvider());
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, scopedServiceProvider: scopedServiceProvider);
+
+            var documents = documentBuilder.Build(entity);
+
+            Assert.False(documents.Data.Attributes.ContainsKey("password"));
+            Assert.True(documents.Data.Attributes.ContainsKey("username"));
+        }
+
+        [Fact]
+        public void Build_Will_Use_Instance_Specific_Resource_If_Defined_For_Multiple_Documents()
+        {
+            var entities = new[] { new User() };
+            var contextGraph = new ContextGraphBuilder()
+                    .AddResource<User>("user")
+                    .Build();
+            _jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+
+            var scopedServiceProvider = new TestScopedServiceProvider(
+                new ServiceCollection()
+                    .AddScoped<ResourceDefinition<User>, InstanceSpecificUserResource>()
+                    .BuildServiceProvider());
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, scopedServiceProvider: scopedServiceProvider);
+
+            var documents = documentBuilder.Build(entities);
+
+            Assert.Single(documents.Data);
+            Assert.False(documents.Data[0].Attributes.ContainsKey("password"));
+            Assert.True(documents.Data[0].Attributes.ContainsKey("username"));
+        }
+
+        [Fact]
+        public void Build_Will_Use_Instance_Specific_Resource_If_Defined_For_Single_Document()
+        {
+            var entity = new User();
+            var contextGraph = new ContextGraphBuilder()
+                    .AddResource<User>("user")
+                    .Build();
+            _jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph);
+
+            var scopedServiceProvider = new TestScopedServiceProvider(
+                new ServiceCollection()
+                    .AddScoped<ResourceDefinition<User>, InstanceSpecificUserResource>()
+                    .BuildServiceProvider());
+
+            var documentBuilder = new DocumentBuilder(_jsonApiContextMock.Object, scopedServiceProvider: scopedServiceProvider);
+
+            var documents = documentBuilder.Build(entity);
+            
+            Assert.False(documents.Data.Attributes.ContainsKey("password"));
+            Assert.True(documents.Data.Attributes.ContainsKey("username"));
+        }
+
+        public class User : Identifiable
+        {
+            [Attr("username")] public string Username { get; set; }
+            [Attr("password")] public string Password { get; set; }
+        }
+
+        public class InstanceSpecificUserResource : ResourceDefinition<User>
+        {
+            protected override List<AttrAttribute> OutputAttrs(User instance)
+                => Remove(user => user.Password);
+        }
+
+        public class UserResource : ResourceDefinition<User>
+        {
+            protected override List<AttrAttribute> OutputAttrs()
+                => Remove(user => user.Password);
+        }
     }
 }
diff --git a/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs b/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
index d2d3ac8319..873b3f50d2 100644
--- a/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
+++ b/test/UnitTests/Controllers/BaseJsonApiController_Tests.cs
@@ -1,4 +1,3 @@
-using System;
 using JsonApiDotNetCore.Controllers;
 using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Services;
diff --git a/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs b/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs
index c7a4a6cb4d..850c459e32 100644
--- a/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs
+++ b/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs
@@ -1,4 +1,3 @@
-using System;
 using System.Collections.Generic;
 using JsonApiDotNetCore.Controllers;
 using JsonApiDotNetCore.Internal;
diff --git a/test/UnitTests/Data/DefaultEntityRepository_Tests.cs b/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
index a8ec56fe9c..5b50fa4cbc 100644
--- a/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
+++ b/test/UnitTests/Data/DefaultEntityRepository_Tests.cs
@@ -1,8 +1,6 @@
 using System;
 using System.Collections.Generic;
 using JsonApiDotNetCore.Controllers;
-using JsonApiDotNetCore.Internal;
-using Microsoft.AspNetCore.Mvc;
 using Xunit;
 using Moq;
 using Microsoft.EntityFrameworkCore;
@@ -51,12 +49,15 @@ public async Task UpdateAsync_Updates_Attributes_In_AttributesToUpdate()
             {
                 Id = _todoItem.Id,
                 Description = Guid.NewGuid().ToString()
-            };
+            };
+
+            var descAttr = new AttrAttribute("description", "Description");
+            descAttr.PropertyInfo = typeof(TodoItem).GetProperty(nameof(TodoItem.Description));
 
             _attrsToUpdate = new Dictionary<AttrAttribute, object> 
             {
                 {
-                    new AttrAttribute("description", "Description"),
+                    descAttr,
                     todoItemUpdates.Description
                 }
             };
diff --git a/test/UnitTests/Models/ResourceDefinitionTests.cs b/test/UnitTests/Models/ResourceDefinitionTests.cs
new file mode 100644
index 0000000000..2112a49447
--- /dev/null
+++ b/test/UnitTests/Models/ResourceDefinitionTests.cs
@@ -0,0 +1,129 @@
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using System.Collections.Generic;
+using Xunit;
+
+namespace UnitTests.Models
+{
+    public class ResourceDefinition_Scenario_Tests
+    {
+        private readonly IContextGraph _graph;
+
+        public ResourceDefinition_Scenario_Tests()
+        {
+            _graph = new ContextGraphBuilder()
+                .AddResource<Model>("models")
+                .Build();
+        }
+
+        [Fact]
+        public void Request_Filter_Uses_Member_Expression()
+        {
+            // arrange
+            var resource = new RequestFilteredResource(isAdmin: true);
+
+            // act
+            var attrs = resource.GetOutputAttrs(null);
+
+            // assert
+            Assert.Single(attrs);
+            Assert.Equal(nameof(Model.Password), attrs[0].InternalAttributeName);
+        }
+
+        [Fact]
+        public void Request_Filter_Uses_NewExpression()
+        {
+            // arrange
+            var resource = new RequestFilteredResource(isAdmin: false);
+
+            // act
+            var attrs = resource.GetOutputAttrs(null);
+
+            // assert
+            Assert.Empty(attrs);
+        }
+
+        [Fact]
+        public void Instance_Filter_Uses_Member_Expression()
+        {
+            // arrange
+            var model = new Model { AlwaysExcluded = "Admin" };
+            var resource = new InstanceFilteredResource();
+
+            // act
+            var attrs = resource.GetOutputAttrs(model);
+
+            // assert
+            Assert.Single(attrs);
+            Assert.Equal(nameof(Model.Password), attrs[0].InternalAttributeName);
+        }
+
+        [Fact]
+        public void Instance_Filter_Uses_NewExpression()
+        {
+            // arrange
+            var model = new Model { AlwaysExcluded = "Joe" };
+            var resource = new InstanceFilteredResource();
+
+            // act
+            var attrs = resource.GetOutputAttrs(model);
+
+            // assert
+            Assert.Empty(attrs);
+        }
+
+        [Fact]
+        public void InstanceOutputAttrsAreSpecified_Returns_True_If_Instance_Method_Is_Overriden()
+        {
+            // act
+            var resource = new InstanceFilteredResource();
+
+            // assert
+            Assert.True(resource._instanceAttrsAreSpecified);
+        }
+        
+        [Fact]
+        public void InstanceOutputAttrsAreSpecified_Returns_False_If_Instance_Method_Is_Not_Overriden()
+        {
+            // act
+            var resource = new RequestFilteredResource(isAdmin: false);
+
+            // assert
+            Assert.False(resource._instanceAttrsAreSpecified);
+        }
+    }
+
+    public class Model : Identifiable
+    {
+        [Attr("name")] public string AlwaysExcluded { get; set; }
+        [Attr("password")] public string Password { get; set; }
+    }
+
+    public class RequestFilteredResource : ResourceDefinition<Model>
+    {
+        private readonly bool _isAdmin;
+
+        // this constructor will be resolved from the container
+        // that means you can take on any dependency that is also defined in the container
+        public RequestFilteredResource(bool isAdmin)
+        {
+            _isAdmin = isAdmin;
+        }
+
+        // Called once per filtered resource in request.
+        protected override List<AttrAttribute> OutputAttrs()
+            => _isAdmin
+                ? Remove(m => m.AlwaysExcluded)
+                : Remove(m => new { m.AlwaysExcluded, m.Password }, from: base.OutputAttrs());
+    }
+    
+    public class InstanceFilteredResource : ResourceDefinition<Model>
+    {
+        // Called once per resource instance
+        protected override List<AttrAttribute> OutputAttrs(Model model)
+            => model.AlwaysExcluded == "Admin"
+                ? Remove(m => m.AlwaysExcluded, base.OutputAttrs())
+                : Remove(m => new { m.AlwaysExcluded, m.Password }, from: base.OutputAttrs());
+    }
+}
diff --git a/test/UnitTests/Services/QueryComposerTests.cs b/test/UnitTests/Services/QueryComposerTests.cs
index 91df486212..330083820c 100644
--- a/test/UnitTests/Services/QueryComposerTests.cs
+++ b/test/UnitTests/Services/QueryComposerTests.cs
@@ -1,7 +1,6 @@
 using System.Collections.Generic;
 using JsonApiDotNetCore.Internal.Query;
 using JsonApiDotNetCore.Services;
-using Microsoft.AspNetCore.Http;
 using Moq;
 using Xunit;
 

From eb35698549ad86cf2ce2ef15d568ded0826499a2 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 2 Jul 2018 12:47:51 -0500
Subject: [PATCH 210/227] feat(csproj): add SourceLink

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index a212eecd70..a75fd0d23a 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -14,6 +14,9 @@
     <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
     <RepositoryType>git</RepositoryType>
     <RepositoryUrl>https://github.com/json-api-dotnet/JsonApiDotNetCore</RepositoryUrl>
+    <PublishRepositoryUrl>true</PublishRepositoryUrl>
+    <EmbedUntrackedSources>true</EmbedUntrackedSources>
+    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
   </PropertyGroup>
 
   <ItemGroup>
@@ -25,6 +28,7 @@
     <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
     <PackageReference Include="System.Memory" Version="4.5.0" />
     <PackageReference Include="System.ValueTuple" Version="$(TuplesVersion)" />
+    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-62925-02" PrivateAssets="All"/>
   </ItemGroup>
 
   <!-- 

From 6ce049a110b9f2594682dd986b0849b9baca3014 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 4 Jul 2018 19:04:09 -0700
Subject: [PATCH 211/227] fix(AttrAttribute): unexpected scenarios cause
 breaking change

---
 src/JsonApiDotNetCore/Models/AttrAttribute.cs | 45 +++++++++++++++++--
 .../Models/ResourceDefinition.cs              |  4 +-
 .../Serialization/JsonApiDeSerializer.cs      |  2 +-
 3 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/src/JsonApiDotNetCore/Models/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
index 017cf72118..d5a30221bb 100644
--- a/src/JsonApiDotNetCore/Models/AttrAttribute.cs
+++ b/src/JsonApiDotNetCore/Models/AttrAttribute.cs
@@ -80,15 +80,54 @@ public AttrAttribute(string publicName, string internalName, bool isImmutable =
         /// Returns null if the attribute does not belong to the
         /// provided object.
         /// </summary>
-        public object GetValue(object entity) => PropertyInfo.GetValue(entity);
+        public object GetValue(object entity)
+        {
+            if (entity == null)
+                throw new InvalidOperationException("Cannot GetValue from null object.");
+
+            var prop = GetResourceProperty(entity);
+            return prop?.GetValue(entity);
+        }
 
         /// <summary>
         /// Sets the value of the attribute on the given object.
         /// </summary>
         public void SetValue(object entity, object newValue)
         {
-            var convertedValue = TypeHelper.ConvertType(newValue, PropertyInfo.PropertyType);
-            PropertyInfo.SetValue(entity, convertedValue);
+            if (entity == null)
+                throw new InvalidOperationException("Cannot SetValue on null object.");
+
+            var prop = GetResourceProperty(entity);
+            if(prop != null)
+            {
+                var convertedValue = TypeHelper.ConvertType(newValue, prop.PropertyType);
+                prop.SetValue(entity, convertedValue);
+            }            
+        }
+
+        private PropertyInfo GetResourceProperty(object resource)
+        {
+            // There are some scenarios, especially ones where users are using a different
+            // data model than view model, where they may use a repository implmentation
+            // that does not match the deserialized type. For now, we will continue to support
+            // this use case.
+            var targetType = resource.GetType();
+            if (targetType != PropertyInfo.DeclaringType)
+            {
+                var propertyInfo = resource
+                    .GetType()
+                    .GetProperty(InternalAttributeName);
+
+                return propertyInfo;
+
+                // TODO: this should throw but will be a breaking change in some cases
+                //if (propertyInfo == null)
+                //    throw new InvalidOperationException(
+                //        $"'{targetType}' does not contain a member named '{InternalAttributeName}'." +
+                //        $"There is also a mismatch in target types. Expected '{PropertyInfo.DeclaringType}' but instead received '{targetType}'.");
+            }
+
+            return PropertyInfo;
         }
 
         /// <summary>
diff --git a/src/JsonApiDotNetCore/Models/ResourceDefinition.cs b/src/JsonApiDotNetCore/Models/ResourceDefinition.cs
index 03ac62390b..64ff918116 100644
--- a/src/JsonApiDotNetCore/Models/ResourceDefinition.cs
+++ b/src/JsonApiDotNetCore/Models/ResourceDefinition.cs
@@ -55,7 +55,7 @@ protected List<AttrAttribute> Remove(Expression<Func<T, dynamic>> filter, List<A
             // model => model.Attribute
             if (filter.Body is MemberExpression memberExpression)
                 return _contextEntity.Attributes
-                        .Where(a => a.PropertyInfo.Name != memberExpression.Member.Name)
+                        .Where(a => a.InternalAttributeName != memberExpression.Member.Name)
                         .ToList();
 
             // model => new { model.Attribute1, model.Attribute2 }
@@ -63,7 +63,7 @@ protected List<AttrAttribute> Remove(Expression<Func<T, dynamic>> filter, List<A
             {
                 var attributes = new List<AttrAttribute>();
                 foreach (var attr in _contextEntity.Attributes)
-                    if (newExpression.Members.Any(m => m.Name == attr.PropertyInfo.Name) == false)
+                    if (newExpression.Members.Any(m => m.Name == attr.InternalAttributeName) == false)
                         attributes.Add(attr);                 
 
                 return attributes;
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 0c3b7217fe..8b5a94f201 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -147,7 +147,7 @@ private object SetEntityAttributes(
                 if (attributeValues.TryGetValue(attr.PublicAttributeName, out object newValue))
                 {
                     var convertedValue = ConvertAttrValue(newValue, attr.PropertyInfo.PropertyType);
-                    attr.PropertyInfo.SetValue(entity, convertedValue);
+                    attr.SetValue(entity, convertedValue);
 
                     if (attr.IsImmutable == false)
                         _jsonApiContext.AttributesToUpdate[attr] = convertedValue;

From f08a79ee4f55753600829f63152c45af83757848 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 4 Jul 2018 19:12:25 -0700
Subject: [PATCH 212/227] chore(build): include symbols in dotnet pack

---
 Build.ps1 | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Build.ps1 b/Build.ps1
index bfbd989415..8ff62d6578 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -46,18 +46,18 @@ If($env:APPVEYOR_REPO_TAG -eq $true) {
 
     IF ([string]::IsNullOrWhitespace($revision)){
         Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts"
-        dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts
+        dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --include-symbols
         CheckLastExitCode
     }
     Else {
         Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision"
-        dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision 
+        dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision --include-symbols
         CheckLastExitCode
     }
 }
 Else { 
     Write-Output "VERSION-SUFFIX: alpha1-$revision"
     Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision"
-    dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision 
+    dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision --include-symbols
     CheckLastExitCode
 }

From 1f633001373248ef39e96b6cbbd458ae231fb59c Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Wed, 4 Jul 2018 19:33:36 -0700
Subject: [PATCH 213/227] specify symbols server for develop

---
 appveyor.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/appveyor.yml b/appveyor.yml
index ec135d19bb..78f4d3187e 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -44,6 +44,7 @@ deploy:
   api_key:
     secure: 6CeYcZ4Ze+57gxfeuHzqP6ldbUkPtF6pfpVM1Gw/K2jExFrAz763gNAQ++tiacq3
   skip_symbols: false
+  symbol_server: https://www.myget.org/F/research-institute/symbols/api/v2/package
   on:
     branch: develop
 - provider: NuGet

From e183da883e894af9a8635f1dd5761239c59e8dcd Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 5 Jul 2018 10:23:22 -0500
Subject: [PATCH 214/227] attempt to reproduce issue in tests

---
 .../Acceptance/Spec/UpdatingDataTests.cs      | 124 +++++++++++++++++-
 1 file changed, 122 insertions(+), 2 deletions(-)

diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs
index 36ea085508..3edb8fa901 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs
@@ -1,10 +1,12 @@
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
 using System.Net.Http.Headers;
 using System.Threading.Tasks;
 using Bogus;
+using JsonApiDotNetCore.Models;
 using JsonApiDotNetCoreExample;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
@@ -49,7 +51,7 @@ public async Task Respond_404_If_EntityDoesNotExist()
 
             var server = new TestServer(builder);
             var client = server.CreateClient();
-            
+
             var content = new
             {
                 data = new
@@ -78,6 +80,124 @@ public async Task Respond_404_If_EntityDoesNotExist()
             Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
         }
 
+
+        [Fact]
+        public async Task Can_Patch_Entity()
+        {
+            // arrange
+            var todoItem = _todoItemFaker.Generate();
+            var person = _personFaker.Generate();
+            todoItem.Owner = person;
+            _context.TodoItems.Add(todoItem);
+            _context.SaveChanges();
+
+            var newTodoItem = _todoItemFaker.Generate();
+
+            var builder = new WebHostBuilder().UseStartup<Startup>();
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+
+            var content = new
+            {
+                data = new
+                {
+                    type = "todo-items",
+                    attributes = new
+                    {
+                        description = newTodoItem.Description,
+                        ordinal = newTodoItem.Ordinal
+                    }
+                }
+            };
+
+            var httpMethod = new HttpMethod("PATCH");
+            var route = $"/api/v1/todo-items/{todoItem.Id}";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await client.SendAsync(request);
+
+            // Assert -- response
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            var body = await response.Content.ReadAsStringAsync();
+            var document = JsonConvert.DeserializeObject<Document>(body);
+            Assert.NotNull(document);
+            Assert.NotNull(document.Data);
+            Assert.NotNull(document.Data.Attributes);
+            Assert.Equal(newTodoItem.Description, document.Data.Attributes["description"]);
+            Assert.Equal(newTodoItem.Ordinal, (long)document.Data.Attributes["ordinal"]);
+            Assert.True(document.Data.Relationships.ContainsKey("owner"));
+            Assert.NotNull(document.Data.Relationships["owner"].SingleData);
+            Assert.Equal(person.Id.ToString(), document.Data.Relationships["owner"].SingleData.Id);
+            Assert.Equal("people", document.Data.Relationships["owner"].SingleData.Type);
+
+            // Assert -- database
+            var updatedTodoItem = _context.TodoItems.AsNoTracking()
+                .Include(t => t.Owner)
+                .SingleOrDefault(t => t.Id == todoItem.Id);
+
+            Assert.Equal(person.Id, updatedTodoItem.OwnerId);
+            Assert.Equal(newTodoItem.Description, updatedTodoItem.Description);
+            Assert.Equal(newTodoItem.Ordinal, updatedTodoItem.Ordinal);
+        }
+
+        [Fact]
+        public async Task Patch_Entity_With_HasMany_Does_Not_Included_Relationships()
+        {
+            // arrange
+            var todoItem = _todoItemFaker.Generate();
+            var person = _personFaker.Generate();
+            todoItem.Owner = person;
+            _context.TodoItems.Add(todoItem);
+            _context.SaveChanges();
+
+            var newPerson = _personFaker.Generate();
+
+            var builder = new WebHostBuilder().UseStartup<Startup>();
+            var server = new TestServer(builder);
+            var client = server.CreateClient();
+
+            var content = new
+            {
+                data = new
+                {
+                    type = "people",
+                    attributes = new Dictionary<string, object>
+                    {
+                        { "last-name",  newPerson.LastName },
+                        { "first-name",  newPerson.FirstName},
+                    }
+                }
+            };
+
+            var httpMethod = new HttpMethod("PATCH");
+            var route = $"/api/v1/people/{person.Id}";
+            var request = new HttpRequestMessage(httpMethod, route);
+
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await client.SendAsync(request);
+
+            // Assert -- response
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            var body = await response.Content.ReadAsStringAsync();
+            var document = JsonConvert.DeserializeObject<Document>(body);
+            Console.WriteLine(body);
+            Assert.NotNull(document);
+            Assert.NotNull(document.Data);
+            Assert.NotNull(document.Data.Attributes);
+            Assert.Equal(newPerson.LastName, document.Data.Attributes["last-name"]);
+            Assert.Equal(newPerson.FirstName, document.Data.Attributes["first-name"]);
+            Assert.True(document.Data.Relationships.ContainsKey("todo-items"));
+            Assert.Null(document.Data.Relationships["todo-items"].ManyData);
+            Assert.Null(document.Data.Relationships["todo-items"].SingleData);
+        }
+
         [Fact]
         public async Task Can_Patch_Entity_And_HasOne_Relationships()
         {
@@ -92,7 +212,7 @@ public async Task Can_Patch_Entity_And_HasOne_Relationships()
                 .UseStartup<Startup>();
             var server = new TestServer(builder);
             var client = server.CreateClient();
-            
+
             var content = new
             {
                 data = new

From d58f2ad7006e3ced3d411d2665857174c064071c Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 5 Jul 2018 11:30:36 -0500
Subject: [PATCH 215/227] chore(appsettings): supress middleware logging

---
 .../appsettings.json                          |  6 ++--
 test/NoEntityFrameworkTests/appsettings.json  |  6 ++--
 test/OperationsExampleTests/appsettings.json  | 28 ++++++++++---------
 3 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/test/JsonApiDotNetCoreExampleTests/appsettings.json b/test/JsonApiDotNetCoreExampleTests/appsettings.json
index c468439079..84f8cf4220 100644
--- a/test/JsonApiDotNetCoreExampleTests/appsettings.json
+++ b/test/JsonApiDotNetCoreExampleTests/appsettings.json
@@ -1,13 +1,15 @@
 {
     "Data": {
-        "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
+        "DefaultConnection":
+            "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
     },
     "Logging": {
         "IncludeScopes": false,
         "LogLevel": {
             "Default": "Warning",
             "System": "Warning",
-            "Microsoft": "Warning"
+            "Microsoft": "Warning",
+            "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter": "Critical"
         }
     }
 }
diff --git a/test/NoEntityFrameworkTests/appsettings.json b/test/NoEntityFrameworkTests/appsettings.json
index c468439079..84f8cf4220 100644
--- a/test/NoEntityFrameworkTests/appsettings.json
+++ b/test/NoEntityFrameworkTests/appsettings.json
@@ -1,13 +1,15 @@
 {
     "Data": {
-        "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
+        "DefaultConnection":
+            "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
     },
     "Logging": {
         "IncludeScopes": false,
         "LogLevel": {
             "Default": "Warning",
             "System": "Warning",
-            "Microsoft": "Warning"
+            "Microsoft": "Warning",
+            "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter": "Critical"
         }
     }
 }
diff --git a/test/OperationsExampleTests/appsettings.json b/test/OperationsExampleTests/appsettings.json
index 73030b1743..84f8cf4220 100644
--- a/test/OperationsExampleTests/appsettings.json
+++ b/test/OperationsExampleTests/appsettings.json
@@ -1,13 +1,15 @@
-{
-    "Data": {
-        "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
-    },
-    "Logging": {
-        "IncludeScopes": false,
-        "LogLevel": {
-            "Default": "Warning",
-            "System": "Warning",
-            "Microsoft": "Warning"
-        }
-    }
-}
+{
+    "Data": {
+        "DefaultConnection":
+            "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres"
+    },
+    "Logging": {
+        "IncludeScopes": false,
+        "LogLevel": {
+            "Default": "Warning",
+            "System": "Warning",
+            "Microsoft": "Warning",
+            "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter": "Critical"
+        }
+    }
+}

From 9758b26d1158db4f5c987ee9e96144a4d3fc1c06 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 5 Jul 2018 11:09:32 -0500
Subject: [PATCH 216/227] fix(relationship pointers): key pointers by
 RelationshipAttribute

---
 .../Request/HasManyRelationshipPointers.cs    | 10 +--
 .../Request/HasOneRelationshipPointers.cs     |  9 ++-
 .../Serialization/JsonApiDeSerializer.cs      | 16 ++---
 .../Acceptance/TodoItemsControllerTests.cs    | 70 +++++++++++++++++++
 4 files changed, 87 insertions(+), 18 deletions(-)

diff --git a/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs b/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
index 721274e3d6..04056e4af8 100644
--- a/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
+++ b/src/JsonApiDotNetCore/Request/HasManyRelationshipPointers.cs
@@ -1,6 +1,6 @@
-using System;
 using System.Collections;
 using System.Collections.Generic;
+using JsonApiDotNetCore.Models;
 
 namespace JsonApiDotNetCore.Request
 {
@@ -32,18 +32,18 @@ namespace JsonApiDotNetCore.Request
     /// </summary>
     public class HasManyRelationshipPointers
     {
-        private Dictionary<Type, IList> _hasManyRelationships = new Dictionary<Type, IList>();
+        private Dictionary<RelationshipAttribute, IList> _hasManyRelationships = new Dictionary<RelationshipAttribute, IList>();
 
         /// <summary>
         /// Add the relationship to the list of relationships that should be 
         /// set in the repository layer.
         /// </summary>
-        public void Add(Type dependentType, IList entities)
-            => _hasManyRelationships[dependentType] = entities;
+        public void Add(RelationshipAttribute relationship, IList entities)
+            => _hasManyRelationships[relationship] = entities;
 
         /// <summary>
         /// Get all the models that should be associated
         /// </summary>
-        public Dictionary<Type, IList> Get() => _hasManyRelationships;
+        public Dictionary<RelationshipAttribute, IList> Get() => _hasManyRelationships;
     }
 }
diff --git a/src/JsonApiDotNetCore/Request/HasOneRelationshipPointers.cs b/src/JsonApiDotNetCore/Request/HasOneRelationshipPointers.cs
index 9e0bdd0e15..753aa35e98 100644
--- a/src/JsonApiDotNetCore/Request/HasOneRelationshipPointers.cs
+++ b/src/JsonApiDotNetCore/Request/HasOneRelationshipPointers.cs
@@ -1,5 +1,4 @@
 using JsonApiDotNetCore.Models;
-using System;
 using System.Collections.Generic;
 
 namespace JsonApiDotNetCore.Request
@@ -29,18 +28,18 @@ namespace JsonApiDotNetCore.Request
     /// </summary>
     public class HasOneRelationshipPointers
     {
-        private Dictionary<Type, IIdentifiable> _hasOneRelationships = new Dictionary<Type, IIdentifiable>();
+        private Dictionary<RelationshipAttribute, IIdentifiable> _hasOneRelationships = new Dictionary<RelationshipAttribute, IIdentifiable>();
 
         /// <summary>
         /// Add the relationship to the list of relationships that should be 
         /// set in the repository layer.
         /// </summary>
-        public void Add(Type dependentType, IIdentifiable entity)
-            => _hasOneRelationships[dependentType] = entity;
+        public void Add(RelationshipAttribute relationship, IIdentifiable entity)
+            => _hasOneRelationships[relationship] = entity;
 
         /// <summary>
         /// Get all the models that should be associated
         /// </summary>
-        public Dictionary<Type, IIdentifiable> Get() => _hasOneRelationships;
+        public Dictionary<RelationshipAttribute, IIdentifiable> Get() => _hasOneRelationships;
     }
 }
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 8b5a94f201..5ad0a2b63d 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -124,7 +124,7 @@ public object DocumentToObject(DocumentData data, List<DocumentData> included =
                             + "If you have manually registered the resource, check that the call to AddResource correctly sets the public name."); ;
 
             var entity = Activator.CreateInstance(contextEntity.EntityType);
-            
+
             entity = SetEntityAttributes(entity, contextEntity, data.Attributes);
             entity = SetRelationships(entity, contextEntity, data.Relationships, included);
 
@@ -141,7 +141,7 @@ private object SetEntityAttributes(
         {
             if (attributeValues == null || attributeValues.Count == 0)
                 return entity;
-            
+
             foreach (var attr in contextEntity.Attributes)
             {
                 if (attributeValues.TryGetValue(attr.PublicAttributeName, out object newValue))
@@ -174,7 +174,7 @@ private object DeserializeComplexType(JContainer obj, Type targetType)
         private object SetRelationships(
             object entity,
             ContextEntity contextEntity,
-            Dictionary<string, RelationshipData> relationships, 
+            Dictionary<string, RelationshipData> relationships,
             List<DocumentData> included = null)
         {
             if (relationships == null || relationships.Count == 0)
@@ -203,7 +203,7 @@ private object SetHasOneRelationship(object entity,
 
             if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData) == false)
                 return entity;
-            
+
             var relationshipAttr = _jsonApiContext.RequestEntity.Relationships
                 .SingleOrDefault(r => r.PublicRelationshipName == relationshipName);
 
@@ -234,7 +234,7 @@ private object SetHasOneRelationship(object entity,
             foreignKeyProperty.SetValue(entity, convertedValue);
 
 
-            if(rio != null
+            if (rio != null
                 // if the resource identifier is null, there should be no reason to instantiate an instance
                 && rio.Id != null)
             {
@@ -247,7 +247,7 @@ private object SetHasOneRelationship(object entity,
                 // we need to store the fact that this relationship was included in the payload
                 // for EF, the repository will use these pointers to make ensure we don't try to
                 // create resources if they already exist, we just need to create the relationship
-                _jsonApiContext.HasOneRelationshipPointers.Add(attr.Type, includedRelationshipObject);
+                _jsonApiContext.HasOneRelationshipPointers.Add(attr, includedRelationshipObject);
             }
 
             return entity;
@@ -278,7 +278,7 @@ private object SetHasManyRelationship(object entity,
 
                 attr.SetValue(entity, convertedCollection);
 
-                _jsonApiContext.HasManyRelationshipPointers.Add(attr.Type, convertedCollection);
+                _jsonApiContext.HasManyRelationshipPointers.Add(attr, convertedCollection);
             }
 
             return entity;
@@ -301,7 +301,7 @@ private IIdentifiable GetIncludedRelationship(ResourceIdentifierObject relatedRe
             var contextEntity = _jsonApiContext.ContextGraph.GetContextEntity(relationshipAttr.Type);
             if (contextEntity == null)
                 throw new JsonApiException(400, $"Included type '{relationshipAttr.Type}' is not a registered json:api resource.");
-            
+
             SetEntityAttributes(relatedInstance, contextEntity, includedResource.Attributes);
 
             return relatedInstance;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
index cf1ea6de96..0600fb402b 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs
@@ -5,10 +5,12 @@
 using System.Net.Http.Headers;
 using System.Threading.Tasks;
 using Bogus;
+using JsonApiDotNetCore.Models;
 using JsonApiDotNetCore.Serialization;
 using JsonApiDotNetCore.Services;
 using JsonApiDotNetCoreExample.Data;
 using JsonApiDotNetCoreExample.Models;
+using Microsoft.EntityFrameworkCore;
 using Newtonsoft.Json;
 using Xunit;
 using Person = JsonApiDotNetCoreExample.Models.Person;
@@ -304,6 +306,74 @@ public async Task Can_Post_TodoItem()
             Assert.Null(deserializedBody.AchievedDate);
         }
 
+
+        [Fact]
+        public async Task Can_Post_TodoItem_With_Different_Owner_And_Assignee()
+        {
+            // Arrange
+            var person1 = new Person();
+            var person2 = new Person();
+            _context.People.Add(person1);
+            _context.People.Add(person2);
+            _context.SaveChanges();
+
+            var todoItem = _todoItemFaker.Generate();
+            var content = new
+            {
+                data = new
+                {
+                    type = "todo-items",
+                    attributes = new Dictionary<string, object>()
+                    {
+                        { "description", todoItem.Description },
+                        { "ordinal", todoItem.Ordinal },
+                        { "created-date", todoItem.CreatedDate }
+                    },
+                    relationships = new
+                    {
+                        owner = new
+                        {
+                            data = new
+                            {
+                                type = "people",
+                                id = person1.Id.ToString()
+                            }
+                        },
+                        assignee = new
+                        {
+                            data = new
+                            {
+                                type = "people",
+                                id = person2.Id.ToString()
+                            }
+                        }
+                    }
+                }
+            };
+
+            var httpMethod = new HttpMethod("POST");
+            var route = $"/api/v1/todo-items";
+
+            var request = new HttpRequestMessage(httpMethod, route);
+            request.Content = new StringContent(JsonConvert.SerializeObject(content));
+            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
+
+            // Act
+            var response = await _fixture.Client.SendAsync(request);
+
+            // Assert -- response
+            Assert.Equal(HttpStatusCode.Created, response.StatusCode);
+            var body = await response.Content.ReadAsStringAsync();
+            var document = JsonConvert.DeserializeObject<Document>(body);
+            var resultId = int.Parse(document.Data.Id);
+
+            // Assert -- database
+            var todoItemResult = await _context.TodoItems.SingleAsync(t => t.Id == resultId);
+
+            Assert.Equal(person1.Id, todoItemResult.OwnerId);
+            Assert.Equal(person2.Id, todoItemResult.AssigneeId);
+        }
+
         [Fact]
         public async Task Can_Patch_TodoItem()
         {

From e28b54bbb037584555493a613550fae1a8311476 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Thu, 5 Jul 2018 11:24:07 -0500
Subject: [PATCH 217/227] chore(csproj): bump version 2.3.5

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index a75fd0d23a..d222f49376 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.3.4</VersionPrefix>
+    <VersionPrefix>2.3.5</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From 64333c731907967251179eef531bb4b0a968f5e3 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 6 Jul 2018 20:19:21 -0500
Subject: [PATCH 218/227] fix(operations): interface hierarchy

---
 .../Services/Operations/Processors/CreateOpProcessor.cs      | 5 +++--
 .../Services/Operations/Processors/GetOpProcessor.cs         | 4 ++--
 .../Services/Operations/Processors/RemoveOpProcessor.cs      | 4 ++--
 .../Services/Operations/Processors/UpdateOpProcessor.cs      | 4 ++--
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
index 4f50bbf4da..5ecdf6f38a 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs
@@ -7,7 +7,7 @@
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
-    public interface ICreateOpProcessor<T> : IOpProcessor
+    public interface ICreateOpProcessor<T> : ICreateOpProcessor<T, int>
         where T : class, IIdentifiable<int>
     { }
 
@@ -15,7 +15,8 @@ public interface ICreateOpProcessor<T, TId> : IOpProcessor
         where T : class, IIdentifiable<TId>
     { }
 
-    public class CreateOpProcessor<T> : CreateOpProcessor<T, int>
+    public class CreateOpProcessor<T>
+        : CreateOpProcessor<T, int>, ICreateOpProcessor<T>
         where T : class, IIdentifiable<int>
     {
         public CreateOpProcessor(
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
index a3737dd57d..a3cb6e7da8 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs
@@ -13,7 +13,7 @@ namespace JsonApiDotNetCore.Services.Operations.Processors
     /// Handles all "<see cref="OperationCode.get"/>" operations 
     /// </summary>
     /// <typeparam name="T">The resource type</typeparam>
-    public interface IGetOpProcessor<T> : IOpProcessor
+    public interface IGetOpProcessor<T> : IGetOpProcessor<T, int>
         where T : class, IIdentifiable<int>
     { }
 
@@ -27,7 +27,7 @@ public interface IGetOpProcessor<T, TId> : IOpProcessor
     { }
 
     /// <inheritdoc />
-    public class GetOpProcessor<T> : GetOpProcessor<T, int>
+    public class GetOpProcessor<T> : GetOpProcessor<T, int>, IGetOpProcessor<T>
         where T : class, IIdentifiable<int>
     {
         /// <inheritdoc />
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
index 236a76d084..a1aebadc66 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs
@@ -7,7 +7,7 @@
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
-    public interface IRemoveOpProcessor<T> : IOpProcessor
+    public interface IRemoveOpProcessor<T> : IRemoveOpProcessor<T, int>
         where T : class, IIdentifiable<int>
     { }
 
@@ -15,7 +15,7 @@ public interface IRemoveOpProcessor<T, TId> : IOpProcessor
         where T : class, IIdentifiable<TId>
     { }
 
-    public class RemoveOpProcessor<T> : RemoveOpProcessor<T, int>
+    public class RemoveOpProcessor<T> : RemoveOpProcessor<T, int>, IRemoveOpProcessor<T>
         where T : class, IIdentifiable<int>
     {
         public RemoveOpProcessor(
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
index b626fbe746..b0000469c8 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
@@ -7,7 +7,7 @@
 
 namespace JsonApiDotNetCore.Services.Operations.Processors
 {
-    public interface IUpdateOpProcessor<T> : IOpProcessor
+    public interface IUpdateOpProcessor<T> : IUpdateOpProcessor<T, int>
         where T : class, IIdentifiable<int>
     { }
 
@@ -15,7 +15,7 @@ public interface IUpdateOpProcessor<T, TId> : IOpProcessor
         where T : class, IIdentifiable<TId>
     { }
 
-    public class UpdateOpProcessor<T> : UpdateOpProcessor<T, int>
+    public class UpdateOpProcessor<T> : UpdateOpProcessor<T, int>, IUpdateOpProcessor<T>
         where T : class, IIdentifiable<int>
     {
         public UpdateOpProcessor(

From 4301a43f055c3fa03ebe4df65d4a62f2686ed649 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Fri, 6 Jul 2018 20:36:31 -0500
Subject: [PATCH 219/227] fix(UpdateOpProcessor): use correct interface

---
 .../Services/Operations/Processors/UpdateOpProcessor.cs         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
index b0000469c8..d22a44a7fe 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
@@ -27,7 +27,7 @@ IContextGraph contextGraph
         { }
     }
 
-    public class UpdateOpProcessor<T, TId> : ICreateOpProcessor<T, TId>
+    public class UpdateOpProcessor<T, TId> : IUpdateOpProcessor<T, TId>
          where T : class, IIdentifiable<TId>
     {
         private readonly IUpdateService<T, TId> _service;

From c31a2e61d7af8991817172d82a27908ed03c5629 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 9 Jul 2018 07:13:39 -0700
Subject: [PATCH 220/227] fix(RequestScopedServiceProvider): do not access
 disposed scope

---
 .../Extensions/IServiceCollectionExtensions.cs             | 1 +
 .../Services/Operations/OperationProcessorResolver.cs      | 4 ++++
 .../Services/Operations/Processors/UpdateOpProcessor.cs    | 7 ++++---
 src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs    | 6 +++---
 4 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index ea15036201..3900630b5d 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -122,6 +122,7 @@ public static void AddJsonApiInternals(
 
             services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
             services.AddScoped(typeof(IResourceService<,>), typeof(EntityResourceService<,>));
+
             services.AddSingleton<JsonApiOptions>(jsonApiOptions);
             services.AddSingleton<IContextGraph>(jsonApiOptions.ContextGraph);
             services.AddScoped<IJsonApiContext, JsonApiContext>();
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
index 4215507bc2..1004ed30dc 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs
@@ -1,3 +1,4 @@
+using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Models.Operations;
 using JsonApiDotNetCore.Services.Operations.Processors;
@@ -90,6 +91,9 @@ public IOpProcessor LocateUpdateService(Operation operation)
             var resource = operation.GetResourceTypeName();
 
             var contextEntity = _context.ContextGraph.GetContextEntity(resource);
+            if (contextEntity == null)
+                throw new JsonApiException(400, $"This API does not expose a resource of type '{resource}'.");
+
             var processor = _processorFactory.GetProcessor<IOpProcessor>(
                 typeof(IUpdateOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType
             );
diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
index d22a44a7fe..1ea690a52c 100644
--- a/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs
@@ -53,16 +53,17 @@ public async Task<Operation> ProcessAsync(Operation operation)
                 throw new JsonApiException(400, "The data.id parameter is required for replace operations");
 
             var model = (T)_deSerializer.DocumentToObject(operation.DataObject);
+
             var result = await _service.UpdateAsync(model.Id, model);
+            if (result == null)
+                throw new JsonApiException(404, $"Could not find an instance of '{operation.DataObject.Type}' with id {operation.DataObject.Id}");
 
             var operationResult = new Operation
             {
                 Op = OperationCode.update
             };
 
-            operationResult.Data = _documentBuilder.GetData(
-                _contextGraph.GetContextEntity(operation.GetResourceTypeName()),
-                result);
+            operationResult.Data = _documentBuilder.GetData(_contextGraph.GetContextEntity(operation.GetResourceTypeName()), result);
 
             return operationResult;
         }
diff --git a/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs b/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs
index 38e147645f..eecd554e7c 100644
--- a/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs
+++ b/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs
@@ -15,14 +15,14 @@ public interface IScopedServiceProvider : IServiceProvider { }
     /// </summary>
     public class RequestScopedServiceProvider : IScopedServiceProvider
     {
-        private readonly IServiceProvider _serviceProvider;
+        private readonly IHttpContextAccessor _httpContextAccessor;
 
         public RequestScopedServiceProvider(IHttpContextAccessor httpContextAccessor)
         {
-            _serviceProvider = httpContextAccessor.HttpContext.RequestServices;
+            _httpContextAccessor = httpContextAccessor;
         }
 
         /// <inheritdoc />
-        public object GetService(Type serviceType) => _serviceProvider.GetService(serviceType);
+        public object GetService(Type serviceType) => _httpContextAccessor.HttpContext.RequestServices.GetService(serviceType);
     }
 }

From 18de6fef3e55e01dad83bbad1be6fd8ae7298cf3 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 9 Jul 2018 16:25:17 -0500
Subject: [PATCH 221/227] reset state between operations

---
 .../Middleware/RequestMiddleware.cs            | 16 ++++++++++++----
 .../Services/IJsonApiContext.cs                |  7 +++++++
 .../Services/JsonApiContext.cs                 | 18 ++++++++++++++----
 .../Services/Operations/OperationsProcessor.cs |  9 +++++++--
 .../Operations/OperationsProcessorTests.cs     |  7 +++++--
 5 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
index 0ce54c8589..ab472a8dba 100644
--- a/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
+++ b/src/JsonApiDotNetCore/Middleware/RequestMiddleware.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Primitives;
 
@@ -9,16 +10,23 @@ namespace JsonApiDotNetCore.Middleware
     public class RequestMiddleware
     {
         private readonly RequestDelegate _next;
-        
+
         public RequestMiddleware(RequestDelegate next)
         {
             _next = next;
         }
 
-        public async Task Invoke(HttpContext context)
+        public async Task Invoke(HttpContext context, IJsonApiContext jsonApiContext)
         {
             if (IsValid(context))
+            {
+                // HACK: this currently results in allocation of
+                // objects that may or may not be used and even double allocation
+                // since the JsonApiContext is using field initializers
+                // Need to work on finding a better solution.
+                jsonApiContext.BeginOperation();
                 await _next(context);
+            }
         }
 
         private static bool IsValid(HttpContext context)
@@ -58,11 +66,11 @@ internal static bool ContainsMediaTypeParameters(string mediaType)
             var incomingMediaTypeSpan = mediaType.AsSpan();
 
             // if the content type is not application/vnd.api+json then continue on
-            if(incomingMediaTypeSpan.Length < Constants.ContentType.Length)
+            if (incomingMediaTypeSpan.Length < Constants.ContentType.Length)
                 return false;
 
             var incomingContentType = incomingMediaTypeSpan.Slice(0, Constants.ContentType.Length);
-            if(incomingContentType.SequenceEqual(Constants.ContentType.AsSpan()) == false)
+            if (incomingContentType.SequenceEqual(Constants.ContentType.AsSpan()) == false)
                 return false;
 
             // anything appended to "application/vnd.api+json;" will be considered a media type param
diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
index 9cbe2a53ca..80995596ea 100644
--- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs
@@ -152,5 +152,12 @@ public interface IJsonApiContext : IJsonApiRequest
 
         [Obsolete("Use the proxied method IControllerContext.GetControllerAttribute instead.")]
         TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute;
+
+        /// <summary>
+        /// **_Experimental_**: do not use. It is likely to change in the future.
+        /// 
+        /// Resets operational state information.
+        /// </summary>
+        void BeginOperation();
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
index 64fcf8e998..1e9b53eb51 100644
--- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs
+++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs
@@ -47,13 +47,14 @@ public JsonApiContext(
         public PageManager PageManager { get; set; }
         public IMetaBuilder MetaBuilder { get; set; }
         public IGenericProcessorFactory GenericProcessorFactory { get; set; }
-        public Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; } = new Dictionary<AttrAttribute, object>();
-        public Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; } = new Dictionary<RelationshipAttribute, object>();
         public Type ControllerType { get; set; }
         public Dictionary<string, object> DocumentMeta { get; set; }
         public bool IsBulkOperationRequest { get; set; }
-        public HasManyRelationshipPointers HasManyRelationshipPointers { get; } = new HasManyRelationshipPointers();
-        public HasOneRelationshipPointers HasOneRelationshipPointers { get; } = new HasOneRelationshipPointers();
+
+        public Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; } = new Dictionary<AttrAttribute, object>();
+        public Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; } = new Dictionary<RelationshipAttribute, object>();
+        public HasManyRelationshipPointers HasManyRelationshipPointers { get; private set; } = new HasManyRelationshipPointers();
+        public HasOneRelationshipPointers HasOneRelationshipPointers { get; private set; } = new HasOneRelationshipPointers();
 
         public IJsonApiContext ApplyContext<T>(object controller)
         {
@@ -132,5 +133,14 @@ private PageManager GetPageManager()
         [Obsolete("Use the proxied method IControllerContext.GetControllerAttribute instead.")]
         public TAttribute GetControllerAttribute<TAttribute>() where TAttribute : Attribute
             => _controllerContext.GetControllerAttribute<TAttribute>();
+
+        public void BeginOperation()
+        {
+            IncludedRelationships = new List<string>();
+            AttributesToUpdate = new Dictionary<AttrAttribute, object>();
+            RelationshipsToUpdate = new Dictionary<RelationshipAttribute, object>();
+            HasManyRelationshipPointers = new HasManyRelationshipPointers();
+            HasOneRelationshipPointers = new HasOneRelationshipPointers();
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
index 7cb9765606..275b4b85b0 100644
--- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
+++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs
@@ -19,13 +19,16 @@ public class OperationsProcessor : IOperationsProcessor
     {
         private readonly IOperationProcessorResolver _processorResolver;
         private readonly DbContext _dbContext;
+        private readonly IJsonApiContext _jsonApiContext;
 
         public OperationsProcessor(
             IOperationProcessorResolver processorResolver,
-            IDbContextResolver dbContextResolver)
+            IDbContextResolver dbContextResolver,
+            IJsonApiContext jsonApiContext)
         {
             _processorResolver = processorResolver;
             _dbContext = dbContextResolver.GetContext();
+            _jsonApiContext = jsonApiContext;
         }
 
         public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
@@ -40,6 +43,7 @@ public async Task<List<Operation>> ProcessAsync(List<Operation> inputOps)
                 {
                     foreach (var op in inputOps)
                     {
+                        _jsonApiContext.BeginOperation();
                         lastAttemptedOperation = op.Op;
                         await ProcessOperation(op, outputOps);
                         opIndex++;
@@ -75,7 +79,8 @@ private async Task ProcessOperation(Operation op, List<Operation> outputOps)
 
         private void ReplaceLocalIdsInResourceObject(ResourceObject resourceObject, List<Operation> outputOps)
         {
-            if (resourceObject == null) return;
+            if (resourceObject == null)
+                return;
 
             // it is strange to me that a top level resource object might use a lid.
             // by not replacing it, we avoid a case where the first operation is an 'add' with an 'lid'
diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
index 9635c6f6f3..08211c5a67 100644
--- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
+++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs
@@ -3,6 +3,7 @@
 using System.Threading.Tasks;
 using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Models.Operations;
+using JsonApiDotNetCore.Services;
 using JsonApiDotNetCore.Services.Operations;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -18,12 +19,14 @@ public class OperationsProcessorTests
         private readonly Mock<IOperationProcessorResolver> _resolverMock;
         public readonly Mock<DbContext> _dbContextMock;
         public readonly Mock<IDbContextResolver> _dbContextResolverMock;
+        public readonly Mock<IJsonApiContext> _jsonApiContextMock;
 
         public OperationsProcessorTests()
         {
             _resolverMock = new Mock<IOperationProcessorResolver>();
             _dbContextMock = new Mock<DbContext>();
             _dbContextResolverMock = new Mock<IDbContextResolver>();
+            _jsonApiContextMock = new Mock<IJsonApiContext>();
         }
 
         [Fact]
@@ -90,7 +93,7 @@ public async Task ProcessAsync_Performs_LocalId_ReplacementAsync_In_Relationship
                 .Returns(opProcessorMock.Object);
 
             _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object);
-            var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextResolverMock.Object);
+            var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextResolverMock.Object, _jsonApiContextMock.Object);
 
             // act
             var results = await operationsProcessor.ProcessAsync(operations);
@@ -173,7 +176,7 @@ public async Task ProcessAsync_Performs_LocalId_ReplacementAsync_In_References()
                 .Returns(updateOpProcessorMock.Object);
 
             _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object);
-            var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextResolverMock.Object);
+            var operationsProcessor = new OperationsProcessor(_resolverMock.Object, _dbContextResolverMock.Object, _jsonApiContextMock.Object);
 
             // act
             var results = await operationsProcessor.ProcessAsync(operations);

From 9e33929a66b2d4c3a9c18df4143de0e13f4cca8e Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 9 Jul 2018 21:49:29 -0500
Subject: [PATCH 222/227] bump minor version

---
 src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index d222f49376..6c7dda3460 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.3.5</VersionPrefix>
+    <VersionPrefix>2.4.0</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From 68802bb69f8e3f46e2e4ce475660cf3a163b0c93 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Tue, 10 Jul 2018 06:47:05 -0500
Subject: [PATCH 223/227] fix(#337): run tests serially

this is because we made the ContextGraph a static instance...if C# ever supports interfaced statics, we could swap the IContextGraph source when the test assembly starts executing
---
 test/UnitTests/xunit.runner.json | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 test/UnitTests/xunit.runner.json

diff --git a/test/UnitTests/xunit.runner.json b/test/UnitTests/xunit.runner.json
new file mode 100644
index 0000000000..9db029ba52
--- /dev/null
+++ b/test/UnitTests/xunit.runner.json
@@ -0,0 +1,4 @@
+{
+  "parallelizeAssembly": false,
+  "parallelizeTestCollections": false
+}

From 34844436a9fe14dcdd147416084e800b3b174871 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 2 Jul 2018 16:03:48 -0700
Subject: [PATCH 224/227] first pass at auto-discovery

---
 .../Data/AppDbContext.cs                      |   6 -
 .../Models/CamelCasedModel.cs                 |   1 +
 .../Models/TodoItemCollection.cs              |   3 +-
 .../JsonApiDotNetCoreExample/Startup.cs       |  22 +--
 src/Examples/ReportsExample/Startup.cs        |  15 +-
 .../Builders/ContextGraphBuilder.cs           |  25 ++--
 .../IServiceCollectionExtensions.cs           |  38 +++--
 .../Graph/IResourceNameFormatter.cs           |  50 +++++++
 .../Graph/ResourceDescriptor.cs               |  16 ++
 .../Graph/ServiceDiscoveryFacade.cs           | 141 ++++++++++++++++++
 src/JsonApiDotNetCore/Graph/TypeLocator.cs    |  93 ++++++++++++
 .../JsonApiDotNetCore.csproj                  |   1 +
 .../Serialization/JsonApiDeSerializer.cs      |   2 +-
 13 files changed, 357 insertions(+), 56 deletions(-)
 create mode 100644 src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
 create mode 100644 src/JsonApiDotNetCore/Graph/ResourceDescriptor.cs
 create mode 100644 src/JsonApiDotNetCore/Graph/ServiceDiscoveryFacade.cs
 create mode 100644 src/JsonApiDotNetCore/Graph/TypeLocator.cs

diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
index 6f50f9aa5b..ec96cadd8e 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs
@@ -1,5 +1,4 @@
 using JsonApiDotNetCoreExample.Models;
-using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
 
 namespace JsonApiDotNetCoreExample.Data
@@ -28,13 +27,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
 
         public DbSet<TodoItem> TodoItems { get; set; }
         public DbSet<Person> People { get; set; }
-
-        [Resource("todo-collections")]
         public DbSet<TodoItemCollection> TodoItemCollections { get; set; }
-
-        [Resource("camelCasedModels")]
         public DbSet<CamelCasedModel> CamelCasedModels { get; set; }
-
         public DbSet<Article> Articles { get; set; }
         public DbSet<Author> Authors { get; set; }
         public DbSet<NonJsonApiResource> NonJsonApiResources { get; set; }
diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/CamelCasedModel.cs b/src/Examples/JsonApiDotNetCoreExample/Models/CamelCasedModel.cs
index 7adf628f38..43d5a43272 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Models/CamelCasedModel.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/CamelCasedModel.cs
@@ -2,6 +2,7 @@
 
 namespace JsonApiDotNetCoreExample.Models
 {
+    [Resource("camelCasedModels")]
     public class CamelCasedModel : Identifiable
     {
         [Attr("compoundAttr")]
diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemCollection.cs b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemCollection.cs
index 95a523dff3..85877b3848 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemCollection.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItemCollection.cs
@@ -4,6 +4,7 @@
 
 namespace JsonApiDotNetCoreExample.Models
 {
+    [Resource("todo-collections")]
     public class TodoItemCollection : Identifiable<Guid>
     {
         [Attr("name")]
@@ -16,4 +17,4 @@ public class TodoItemCollection : Identifiable<Guid>
         [HasOne("owner")]
         public virtual Person Owner { get; set; }
     }
-}
\ No newline at end of file
+}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Startup.cs b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
index ec1bdc544c..29dfc9e4b5 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Startup.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Startup.cs
@@ -7,9 +7,6 @@
 using Microsoft.EntityFrameworkCore;
 using JsonApiDotNetCore.Extensions;
 using System;
-using JsonApiDotNetCore.Models;
-using JsonApiDotNetCoreExample.Resources;
-using JsonApiDotNetCoreExample.Models;
 
 namespace JsonApiDotNetCoreExample
 {
@@ -33,23 +30,20 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
             var loggerFactory = new LoggerFactory();
             loggerFactory.AddConsole(LogLevel.Warning);
 
+            var mvcBuilder = services.AddMvcCore();
+
             services
                 .AddSingleton<ILoggerFactory>(loggerFactory)
-                .AddDbContext<AppDbContext>(options =>
-                    options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient)
-                .AddJsonApi<AppDbContext>(options => {
+                .AddDbContext<AppDbContext>(options => options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient)
+                .AddJsonApi(options => {
                     options.Namespace = "api/v1";
                     options.DefaultPageSize = 5;
                     options.IncludeTotalRecordCount = true;
-                })
-                // TODO: this should be handled via auto-discovery
-                .AddScoped<ResourceDefinition<User>, UserResource>();
+                }, 
+                mvcBuilder,
+                discovery => discovery.AddCurrentAssemblyServices());
 
-            var provider = services.BuildServiceProvider();
-            var appContext = provider.GetRequiredService<AppDbContext>();
-            if(appContext == null)
-                throw new ArgumentException();
-                
+            var provider = services.BuildServiceProvider();                
             return provider;
         }
 
diff --git a/src/Examples/ReportsExample/Startup.cs b/src/Examples/ReportsExample/Startup.cs
index fe476c0406..43a910a0e6 100644
--- a/src/Examples/ReportsExample/Startup.cs
+++ b/src/Examples/ReportsExample/Startup.cs
@@ -1,5 +1,4 @@
 using JsonApiDotNetCore.Extensions;
-using JsonApiDotNetCore.Services;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.Extensions.Configuration;
@@ -26,16 +25,10 @@ public Startup(IHostingEnvironment env)
         public virtual void ConfigureServices(IServiceCollection services)
         {
             var mvcBuilder = services.AddMvcCore();
-            services.AddJsonApi(opt =>
-            {
-                opt.BuildContextGraph(builder =>
-                {
-                    builder.AddResource<Report>("reports");
-                });
-                opt.Namespace = "api";
-            }, mvcBuilder);
-
-            services.AddScoped<IGetAllService<Report>, ReportService>();
+            services.AddJsonApi(
+                opt => opt.Namespace = "api", 
+                mvcBuilder,
+                discovery => discovery.AddCurrentAssemblyServices());
         }
 
         public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index 080c0a6bb7..1d9ef83ecd 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -3,6 +3,7 @@
 using System.Linq;
 using System.Reflection;
 using JsonApiDotNetCore.Extensions;
+using JsonApiDotNetCore.Graph;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Models;
 using Microsoft.EntityFrameworkCore;
@@ -32,6 +33,14 @@ public interface IContextGraphBuilder
         /// <param name="pluralizedTypeName">The pluralized name that should be exposed by the API</param>
         IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>;
 
+        /// <summary>
+        /// Add a json:api resource
+        /// </summary>
+        /// <param name="entityType">The resource model type</param>
+        /// <param name="idType">The resource model identifier type</param>
+        /// <param name="pluralizedTypeName">The pluralized name that should be exposed by the API</param>
+        IContextGraphBuilder AddResource(Type entityType, Type idType, string pluralizedTypeName);
+
         /// <summary>
         /// Add all the models that are part of the provided <see cref="DbContext" /> 
         /// that also implement <see cref="IIdentifiable"/>
@@ -66,12 +75,13 @@ public IContextGraphBuilder AddResource<TResource>(string pluralizedTypeName) wh
             => AddResource<TResource, int>(pluralizedTypeName);
 
         public IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>
-        {
-            var entityType = typeof(TResource);
+            => AddResource(typeof(TResource), typeof(TId), pluralizedTypeName);
 
+        public IContextGraphBuilder AddResource(Type entityType, Type idType, string pluralizedTypeName)
+        {
             AssertEntityIsNotAlreadyDefined(entityType);
 
-            _entities.Add(GetEntity(pluralizedTypeName, entityType, typeof(TId)));
+            _entities.Add(GetEntity(pluralizedTypeName, entityType, idType));
 
             return this;
         }
@@ -182,12 +192,9 @@ private string GetResourceName(PropertyInfo property)
 
         private (bool isJsonApiResource, Type idType) GetIdType(Type resourceType)
         {
-            var interfaces = resourceType.GetInterfaces();
-            foreach (var type in interfaces)
-            {
-                if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(IIdentifiable<>))
-                    return (true, type.GetGenericArguments()[0]);
-            }
+            var possible = TypeLocator.GetIdType(resourceType);
+            if (possible.isJsonApiResource)
+                return possible;
 
             _validationResults.Add(new ValidationResult(LogLevel.Warning, $"{resourceType} does not implement 'IIdentifiable<>'. "));
 
diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
index 3900630b5d..ea597ef011 100644
--- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs
@@ -3,6 +3,7 @@
 using JsonApiDotNetCore.Configuration;
 using JsonApiDotNetCore.Data;
 using JsonApiDotNetCore.Formatters;
+using JsonApiDotNetCore.Graph;
 using JsonApiDotNetCore.Internal;
 using JsonApiDotNetCore.Internal.Generics;
 using JsonApiDotNetCore.Middleware;
@@ -34,9 +35,10 @@ public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection se
             return AddJsonApi<TContext>(services, options, mvcBuilder);
         }
 
-        public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services,
-           Action<JsonApiOptions> options,
-           IMvcCoreBuilder mvcBuilder) where TContext : DbContext
+        public static IServiceCollection AddJsonApi<TContext>(
+            this IServiceCollection services,
+            Action<JsonApiOptions> options,
+            IMvcCoreBuilder mvcBuilder) where TContext : DbContext
         {
             var config = new JsonApiOptions();
 
@@ -44,8 +46,7 @@ public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection se
 
             config.BuildContextGraph(builder => builder.AddDbContext<TContext>());
 
-            mvcBuilder
-                .AddMvcOptions(opt =>
+            mvcBuilder.AddMvcOptions(opt =>
                 {
                     opt.Filters.Add(typeof(JsonApiExceptionFilter));
                     opt.SerializeAsJsonApi(config);
@@ -55,22 +56,28 @@ public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection se
             return services;
         }
 
-        public static IServiceCollection AddJsonApi(this IServiceCollection services,
-            Action<JsonApiOptions> options,
-            IMvcCoreBuilder mvcBuilder)
+        public static IServiceCollection AddJsonApi(
+            this IServiceCollection services,
+            Action<JsonApiOptions> configureOptions,
+            IMvcCoreBuilder mvcBuilder,
+            Action<ServiceDiscoveryFacade> autoDiscover = null)
         {
-            var config = new JsonApiOptions();
+            var options = new JsonApiOptions();
+            configureOptions(options);
 
-            options(config);
+            if(autoDiscover != null)
+            {
+                var facade = new ServiceDiscoveryFacade(services, options.ContextGraphBuilder);
+                autoDiscover(facade);
+            }
 
-            mvcBuilder
-                .AddMvcOptions(opt =>
+            mvcBuilder.AddMvcOptions(opt =>
                 {
                     opt.Filters.Add(typeof(JsonApiExceptionFilter));
-                    opt.SerializeAsJsonApi(config);
+                    opt.SerializeAsJsonApi(options);
                 });
 
-            AddJsonApiInternals(services, config);
+            AddJsonApiInternals(services, options);
             return services;
         }
 
@@ -90,6 +97,9 @@ public static void AddJsonApiInternals(
             this IServiceCollection services,
             JsonApiOptions jsonApiOptions)
         {
+            if (jsonApiOptions.ContextGraph == null)
+                jsonApiOptions.ContextGraph = jsonApiOptions.ContextGraphBuilder.Build();
+
             if (jsonApiOptions.ContextGraph.UsesDbContext == false)
             {
                 services.AddScoped<DbContext>();
diff --git a/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs b/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
new file mode 100644
index 0000000000..021a3399e6
--- /dev/null
+++ b/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Humanizer;
+using JsonApiDotNetCore.Models;
+using str = JsonApiDotNetCore.Extensions.StringExtensions;
+
+
+namespace JsonApiDotNetCore.Graph
+{
+    /// <summary>
+    /// Provides an interface for formatting resource names by convention
+    /// </summary>
+    public interface IResourceNameFormatter
+    {
+        /// <summary>
+        /// Get the publicly visible resource name from the internal type name
+        /// </summary>
+        string FormatResourceName(Type resourceType);
+    }
+
+    public class DefaultResourceNameFormatter : IResourceNameFormatter
+    {
+        /// <summary>
+        /// Uses the internal type name to determine the external resource name.
+        /// By default we us Humanizer for pluralization and then we dasherize the name.
+        /// </summary>
+        /// <example>
+        /// <code>
+        /// _default.FormatResourceName(typeof(TodoItem)).Dump(); 
+        /// // > "todo-items"
+        /// </code>
+        /// </example>
+        public string FormatResourceName(Type type)
+        {
+            try
+            {
+                var attribute = type.GetCustomAttributes(typeof(ResourceAttribute)).SingleOrDefault() as ResourceAttribute;
+                if (attribute != null)
+                    return attribute.ResourceName;
+
+                return str.Dasherize(type.Name.Pluralize());
+            }
+            catch (InvalidOperationException e)
+            {
+                throw new InvalidOperationException($"Cannot define multiple {nameof(ResourceAttribute)}s on type '{type}'.", e);
+            }
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Graph/ResourceDescriptor.cs b/src/JsonApiDotNetCore/Graph/ResourceDescriptor.cs
new file mode 100644
index 0000000000..e90bcdc22c
--- /dev/null
+++ b/src/JsonApiDotNetCore/Graph/ResourceDescriptor.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace JsonApiDotNetCore.Graph
+{
+    internal struct ResourceDescriptor
+    {
+        public ResourceDescriptor(Type resourceType, Type idType)
+        {
+            ResourceType = resourceType;
+            IdType = idType;
+        }
+
+        public Type ResourceType { get; set; }
+        public Type IdType { get; set; }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Graph/ServiceDiscoveryFacade.cs b/src/JsonApiDotNetCore/Graph/ServiceDiscoveryFacade.cs
new file mode 100644
index 0000000000..ca156718fe
--- /dev/null
+++ b/src/JsonApiDotNetCore/Graph/ServiceDiscoveryFacade.cs
@@ -0,0 +1,141 @@
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Data;
+using JsonApiDotNetCore.Internal;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Services;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Linq;
+using System.Reflection;
+
+namespace JsonApiDotNetCore.Graph
+{
+    public class ServiceDiscoveryFacade
+    {
+        private readonly IServiceCollection _services;
+        private readonly IContextGraphBuilder _graphBuilder;
+
+        public ServiceDiscoveryFacade(IServiceCollection services, IContextGraphBuilder graphBuilder)
+        {
+            _services = services;
+            _graphBuilder = graphBuilder;
+        }
+
+        /// <summary>
+        /// Add resources, services and repository implementations to the container.
+        /// </summary>
+        /// <param name="resourceNameFormatter">The type name formatter used to get the string representation of resource names.</param>
+        public ServiceDiscoveryFacade AddCurrentAssemblyServices(IResourceNameFormatter resourceNameFormatter = null)
+            => AddAssemblyServices(Assembly.GetCallingAssembly(), resourceNameFormatter);
+
+        /// <summary>
+        /// Add resources, services and repository implementations to the container.
+        /// </summary>
+        /// <param name="assembly">The assembly to search for resources in.</param>
+        /// <param name="resourceNameFormatter">The type name formatter used to get the string representation of resource names.</param>
+        public ServiceDiscoveryFacade AddAssemblyServices(Assembly assembly, IResourceNameFormatter resourceNameFormatter = null)
+        {
+            AddDbContextResolvers(assembly);
+            AddAssemblyResources(assembly, resourceNameFormatter);
+            AddAssemblyServices(assembly);
+            AddAssemblyRepositories(assembly);
+
+            return this;
+        }
+
+        private void AddDbContextResolvers(Assembly assembly)
+        {
+            var dbContextTypes = TypeLocator.GetDerivedTypes(assembly, typeof(DbContext));
+            foreach(var dbContextType in dbContextTypes)
+            {
+                var resolverType = typeof(DbContextResolver<>).MakeGenericType(dbContextType);
+                _services.AddScoped(typeof(IDbContextResolver), resolverType);
+            }
+        }
+
+        /// <summary>
+        /// Adds resources to the graph and registers <see cref="ResourceDefinition{T}"/> types on the container.
+        /// </summary>
+        /// <param name="assembly">The assembly to search for resources in.</param>
+        /// <param name="resourceNameFormatter">The type name formatter used to get the string representation of resource names.</param>
+        public ServiceDiscoveryFacade AddAssemblyResources(Assembly assembly, IResourceNameFormatter resourceNameFormatter = null)
+        {
+            var identifiables = TypeLocator.GetIdentifableTypes(assembly);
+            foreach (var identifiable in identifiables)
+            {
+                RegisterResourceDefinition(assembly, identifiable);
+                AddResourceToGraph(identifiable, resourceNameFormatter);
+            }
+
+            return this;
+        }
+
+        private void RegisterResourceDefinition(Assembly assembly, ResourceDescriptor identifiable)
+        {
+            try
+            {
+                var resourceDefinition = TypeLocator.GetDerivedGenericTypes(assembly, typeof(ResourceDefinition<>), identifiable.ResourceType)
+                    .SingleOrDefault();
+
+                if (resourceDefinition != null)
+                    _services.AddScoped(typeof(ResourceDefinition<>).MakeGenericType(identifiable.ResourceType), resourceDefinition);
+            }
+            catch (InvalidOperationException e)
+            {
+                // TODO: need a better way to communicate failure since this is unlikely to occur during a web request
+                throw new JsonApiException(500,
+                    $"Cannot define multiple ResourceDefinition<> implementations for '{identifiable.ResourceType}'", e);
+            }            
+        }
+
+        private void AddResourceToGraph(ResourceDescriptor identifiable, IResourceNameFormatter resourceNameFormatter = null)
+        {
+            var resourceName = FormatResourceName(identifiable.ResourceType, resourceNameFormatter);
+            _graphBuilder.AddResource(identifiable.ResourceType, identifiable.IdType, resourceName);
+        }
+
+        private string FormatResourceName(Type resourceType, IResourceNameFormatter resourceNameFormatter)
+        {
+            resourceNameFormatter = resourceNameFormatter ?? new DefaultResourceNameFormatter();
+            return resourceNameFormatter.FormatResourceName(resourceType);
+        }
+
+        /// <summary>
+        /// Add <see cref="IResourceService{T, TId}"/> implementations to container.
+        /// </summary>
+        /// <param name="assembly">The assembly to search for resources in.</param>
+        public ServiceDiscoveryFacade AddAssemblyServices(Assembly assembly)
+        {
+            RegisterServiceImplementations(assembly, typeof(IResourceService<,>));
+            RegisterServiceImplementations(assembly, typeof(ICreateService<,>));
+            RegisterServiceImplementations(assembly, typeof(IGetAllService<,>));
+            RegisterServiceImplementations(assembly, typeof(IGetByIdService<,>));
+            RegisterServiceImplementations(assembly, typeof(IGetRelationshipService<,>));
+            RegisterServiceImplementations(assembly, typeof(IUpdateService<,>));
+            RegisterServiceImplementations(assembly, typeof(IDeleteService<,>));
+
+            return this;
+        }
+
+        /// <summary>
+        /// Add <see cref="IEntityRepository{T, TId}"/> implementations to container.
+        /// </summary>
+        /// <param name="assembly">The assembly to search for resources in.</param>
+        public ServiceDiscoveryFacade AddAssemblyRepositories(Assembly assembly)
+            => RegisterServiceImplementations(assembly, typeof(IEntityRepository<,>));
+
+        private ServiceDiscoveryFacade RegisterServiceImplementations(Assembly assembly, Type interfaceType)
+        {
+            var identifiables = TypeLocator.GetIdentifableTypes(assembly);
+            foreach (var identifiable in identifiables)
+            {
+                var service = TypeLocator.GetGenericInterfaceImplementation(assembly, interfaceType, identifiable.ResourceType, identifiable.IdType);
+                if (service.implementation != null)
+                    _services.AddScoped(service.registrationInterface, service.implementation);
+            }
+
+            return this;
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/Graph/TypeLocator.cs b/src/JsonApiDotNetCore/Graph/TypeLocator.cs
new file mode 100644
index 0000000000..6cd2e89c43
--- /dev/null
+++ b/src/JsonApiDotNetCore/Graph/TypeLocator.cs
@@ -0,0 +1,93 @@
+using JsonApiDotNetCore.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace JsonApiDotNetCore.Graph
+{
+    internal static class TypeLocator
+    {
+        private static Dictionary<Assembly, Type[]> _typeCache = new Dictionary<Assembly, Type[]>();
+        private static Dictionary<Assembly, List<ResourceDescriptor>> _identifiableTypeCache = new Dictionary<Assembly, List<ResourceDescriptor>>();
+        
+        public static (bool isJsonApiResource, Type idType) GetIdType(Type resourceType)
+        {
+            var identitifableType = GetIdentifiableIdType(resourceType);
+            return (identitifableType != null)
+                ? (true, identitifableType)
+                : (false, null);
+        }
+
+        private static Type GetIdentifiableIdType(Type identifiableType)
+            => GetIdentifiableInterface(identifiableType)?.GetGenericArguments()[0];
+
+        private static Type GetIdentifiableInterface(Type type)
+            => type.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IIdentifiable<>));
+
+        // TODO: determine if this optimization is even helpful...
+        private static Type[] GetAssemblyTypes(Assembly assembly)
+        {
+            if (_typeCache.TryGetValue(assembly, out var types) == false)
+            {
+                types = assembly.GetTypes();
+                _typeCache[assembly] = types;
+            }
+
+            return types;
+        }
+
+        public static List<ResourceDescriptor> GetIdentifableTypes(Assembly assembly)
+        {
+            if (_identifiableTypeCache.TryGetValue(assembly, out var descriptors) == false)
+            {
+                descriptors = new List<ResourceDescriptor>();
+                _identifiableTypeCache[assembly] = descriptors;
+
+                foreach (var type in assembly.GetTypes())
+                {
+                    var possible = GetIdType(type);
+                    if (possible.isJsonApiResource)
+                        descriptors.Add(new ResourceDescriptor(type, possible.idType));
+                }
+            }
+
+            return descriptors;
+        }
+
+        public static (Type implementation, Type registrationInterface) GetGenericInterfaceImplementation(Assembly assembly, Type openGenericInterfaceType, params Type[] genericInterfaceArguments)
+        {
+            foreach (var type in assembly.GetTypes())
+            {
+                var interfaces = type.GetInterfaces();
+                foreach (var interfaceType in interfaces)
+                    if (interfaceType.GetTypeInfo().IsGenericType && interfaceType.GetGenericTypeDefinition() == openGenericInterfaceType)
+                        return (
+                            type,
+                            interfaceType.MakeGenericType(genericInterfaceArguments)
+                        );
+            }
+
+            return (null, null);
+        }
+
+        public static IEnumerable<Type> GetDerivedGenericTypes(Assembly assembly, Type openGenericType, Type genericArgument)
+        {
+            var genericType = openGenericType.MakeGenericType(genericArgument);
+            foreach (var type in assembly.GetTypes())
+            {
+                if (genericType.IsAssignableFrom(type))
+                    yield return type;
+            }
+        }
+
+        public static IEnumerable<Type> GetDerivedTypes(Assembly assembly, Type inheritedType)
+        {
+            foreach (var type in assembly.GetTypes())
+            {
+                if(inheritedType.IsAssignableFrom(type))
+                    yield return type;
+            }
+        }
+    }
+}
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 6c7dda3460..f1cecab65d 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -21,6 +21,7 @@
 
   <ItemGroup>
     <PackageReference Include="Ben.Demystifier" Version="0.1.1" />
+    <PackageReference Include="Humanizer" Version="2.4.2" />
     <PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="$(AspNetCoreVersion)" />
     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
index 5ad0a2b63d..22bbe86543 100644
--- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
+++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs
@@ -121,7 +121,7 @@ public object DocumentToObject(DocumentData data, List<DocumentData> included =
                     message: $"This API does not contain a json:api resource named '{data.Type}'.",
                     detail: "This resource is not registered on the ContextGraph. "
                             + "If you are using Entity Framework, make sure the DbSet matches the expected resource name. "
-                            + "If you have manually registered the resource, check that the call to AddResource correctly sets the public name."); ;
+                            + "If you have manually registered the resource, check that the call to AddResource correctly sets the public name.");
 
             var entity = Activator.CreateInstance(contextEntity.EntityType);
 

From 7074002da5b7b8a2e25bf4d697f153dff7e63a35 Mon Sep 17 00:00:00 2001
From: jaredcnance <jaredcnance@gmail.com>
Date: Mon, 2 Jul 2018 16:41:06 -0700
Subject: [PATCH 225/227] fix tests

---
 .../Builders/ContextGraphBuilder.cs           | 21 ++++++++++++-------
 .../Graph/IResourceNameFormatter.cs           |  3 +--
 .../Internal/ContextEntity.cs                 |  4 +++-
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index 1d9ef83ecd..e7de302075 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -174,20 +174,27 @@ public IContextGraphBuilder AddDbContext<T>() where T : DbContext
                     var (isJsonApiResource, idType) = GetIdType(entityType);
 
                     if (isJsonApiResource)
-                        _entities.Add(GetEntity(GetResourceName(property), entityType, idType));
+                        _entities.Add(GetEntity(GetResourceName(property, entityType), entityType, idType));
                 }
             }
 
             return this;
         }
 
-        private string GetResourceName(PropertyInfo property)
+        private string GetResourceName(PropertyInfo property, Type resourceType)
         {
-            var resourceAttribute = property.GetCustomAttribute(typeof(ResourceAttribute));
-            if (resourceAttribute == null)
-                return property.Name.Dasherize();
-
-            return ((ResourceAttribute)resourceAttribute).ResourceName;
+            // check the class definition first
+            // [Resource("models"] public class Model : Identifiable { /* ... */ }
+            if (resourceType.GetCustomAttribute(typeof(ResourceAttribute)) is ResourceAttribute classResourceAttribute)
+                return classResourceAttribute.ResourceName;
+
+            // check the DbContext member next
+            // [Resource("models")] public DbSet<Model> Models { get; set; }
+            if (property.GetCustomAttribute(typeof(ResourceAttribute)) is ResourceAttribute resourceAttribute)
+                return resourceAttribute.ResourceName;
+
+            // fallback to dsherized...this should actually check for a custom IResourceNameFormatter
+            return property.Name.Dasherize();            
         }
 
         private (bool isJsonApiResource, Type idType) GetIdType(Type resourceType)
diff --git a/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs b/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
index 021a3399e6..c67852620e 100644
--- a/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
+++ b/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
@@ -35,8 +35,7 @@ public string FormatResourceName(Type type)
         {
             try
             {
-                var attribute = type.GetCustomAttributes(typeof(ResourceAttribute)).SingleOrDefault() as ResourceAttribute;
-                if (attribute != null)
+                if (type.GetCustomAttribute(typeof(ResourceAttribute)) is ResourceAttribute attribute)
                     return attribute.ResourceName;
 
                 return str.Dasherize(type.Name.Pluralize());
diff --git a/src/JsonApiDotNetCore/Internal/ContextEntity.cs b/src/JsonApiDotNetCore/Internal/ContextEntity.cs
index 1e15a9c6bc..867a04350c 100644
--- a/src/JsonApiDotNetCore/Internal/ContextEntity.cs
+++ b/src/JsonApiDotNetCore/Internal/ContextEntity.cs
@@ -9,7 +9,9 @@ public class ContextEntity
         /// <summary>
         /// The exposed resource name
         /// </summary>
-        public string EntityName { get; set; }
+        public string EntityName {
+            get;
+            set; }
 
         /// <summary>
         /// The data model type

From 36a9ffe33a52c3855c61c146e993049661927da6 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Sat, 11 Aug 2018 21:51:59 -0700
Subject: [PATCH 226/227] use IResourceNameFormatter in ContextGraph add
 documentation

---
 .../Builders/ContextGraphBuilder.cs           | 25 +++++++--
 src/JsonApiDotNetCore/Graph/TypeLocator.cs    | 54 ++++++++++++++++---
 .../JsonApiDotNetCore.csproj                  |  2 +-
 3 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index e7de302075..6c836cdaca 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -48,6 +48,12 @@ public interface IContextGraphBuilder
         /// <typeparam name="T">The <see cref="DbContext"/> implementation type.</typeparam>
         IContextGraphBuilder AddDbContext<T>() where T : DbContext;
 
+        /// <summary>
+        /// Specify the <see cref="IResourceNameFormatter"/> used to format resource names.
+        /// </summary>
+        /// <param name="resourceNameFormatter">Formatter used to define exposed resource names by convention.</param>
+        IContextGraphBuilder UseNameFormatter(IResourceNameFormatter resourceNameFormatter);
+
         /// <summary>
         /// Which links to include. Defaults to <see cref="Link.All"/>.
         /// </summary>
@@ -60,6 +66,8 @@ public class ContextGraphBuilder : IContextGraphBuilder
         private List<ValidationResult> _validationResults = new List<ValidationResult>();
 
         private bool _usesDbContext;
+        private IResourceNameFormatter _resourceNameFormatter = new DefaultResourceNameFormatter();
+
         public Link DocumentLinks { get; set; } = Link.All;
 
         public IContextGraph Build()
@@ -71,12 +79,15 @@ public IContextGraph Build()
             return graph;
         }
 
+        /// <inheritdoc />
         public IContextGraphBuilder AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>
             => AddResource<TResource, int>(pluralizedTypeName);
 
+        /// <inheritdoc />
         public IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>
             => AddResource(typeof(TResource), typeof(TId), pluralizedTypeName);
 
+        /// <inheritdoc />
         public IContextGraphBuilder AddResource(Type entityType, Type idType, string pluralizedTypeName)
         {
             AssertEntityIsNotAlreadyDefined(entityType);
@@ -152,6 +163,7 @@ protected virtual Type GetRelationshipType(RelationshipAttribute relation, Prope
 
         private Type GetResourceDefinitionType(Type entityType) => typeof(ResourceDefinition<>).MakeGenericType(entityType);
 
+        /// <inheritdoc />
         public IContextGraphBuilder AddDbContext<T>() where T : DbContext
         {
             _usesDbContext = true;
@@ -174,14 +186,14 @@ public IContextGraphBuilder AddDbContext<T>() where T : DbContext
                     var (isJsonApiResource, idType) = GetIdType(entityType);
 
                     if (isJsonApiResource)
-                        _entities.Add(GetEntity(GetResourceName(property, entityType), entityType, idType));
+                        _entities.Add(GetEntity(GetResourceNameFromDbSetProperty(property, entityType), entityType, idType));
                 }
             }
 
             return this;
         }
 
-        private string GetResourceName(PropertyInfo property, Type resourceType)
+        private string GetResourceNameFromDbSetProperty(PropertyInfo property, Type resourceType)
         {
             // check the class definition first
             // [Resource("models"] public class Model : Identifiable { /* ... */ }
@@ -194,7 +206,7 @@ private string GetResourceName(PropertyInfo property, Type resourceType)
                 return resourceAttribute.ResourceName;
 
             // fallback to dsherized...this should actually check for a custom IResourceNameFormatter
-            return property.Name.Dasherize();            
+            return _resourceNameFormatter.FormatResourceName(resourceType);
         }
 
         private (bool isJsonApiResource, Type idType) GetIdType(Type resourceType)
@@ -213,5 +225,12 @@ private void AssertEntityIsNotAlreadyDefined(Type entityType)
             if (_entities.Any(e => e.EntityType == entityType))
                 throw new InvalidOperationException($"Cannot add entity type {entityType} to context graph, there is already an entity of that type configured.");
         }
+
+        /// <inheritdoc />
+        public IContextGraphBuilder UseNameFormatter(IResourceNameFormatter resourceNameFormatter)
+        {
+            _resourceNameFormatter = resourceNameFormatter;
+            return this;
+        }
     }
 }
diff --git a/src/JsonApiDotNetCore/Graph/TypeLocator.cs b/src/JsonApiDotNetCore/Graph/TypeLocator.cs
index 6cd2e89c43..5bdb029e50 100644
--- a/src/JsonApiDotNetCore/Graph/TypeLocator.cs
+++ b/src/JsonApiDotNetCore/Graph/TypeLocator.cs
@@ -6,11 +6,19 @@
 
 namespace JsonApiDotNetCore.Graph
 {
+    /// <summary>
+    /// Used to locate types and facilitate auto-resource discovery
+    /// </summary>
     internal static class TypeLocator
     {
         private static Dictionary<Assembly, Type[]> _typeCache = new Dictionary<Assembly, Type[]>();
         private static Dictionary<Assembly, List<ResourceDescriptor>> _identifiableTypeCache = new Dictionary<Assembly, List<ResourceDescriptor>>();
+
         
+        /// <summary>
+        /// Determine whether or not this is a json:api resource by checking if it implements <see cref="IIdentifiable"/>.
+        /// Returns the status and the resultant id type, either `(true, Type)` OR `(false, null)`
+        /// </summary>        
         public static (bool isJsonApiResource, Type idType) GetIdType(Type resourceType)
         {
             var identitifableType = GetIdentifiableIdType(resourceType);
@@ -37,6 +45,10 @@ private static Type[] GetAssemblyTypes(Assembly assembly)
             return types;
         }
 
+
+        /// <summary>
+        /// Get all implementations of <see cref="IIdentifiable"/>. in the assembly
+        /// </summary>
         public static List<ResourceDescriptor> GetIdentifableTypes(Assembly assembly)
         {
             if (_identifiableTypeCache.TryGetValue(assembly, out var descriptors) == false)
@@ -55,6 +67,17 @@ public static List<ResourceDescriptor> GetIdentifableTypes(Assembly assembly)
             return descriptors;
         }
 
+        /// <summary>
+        /// Get all implementations of the generic interface
+        /// </summary>
+        /// <param name="assembly">The assembly to search</param>
+        /// <param name="openGenericInterfaceType">The open generic type, e.g. `typeof(IResourceService&lt;&gt;)`</param>
+        /// <param name="genericInterfaceArguments">Parameters to the generic type</param>
+        /// <example>
+        /// <code>
+        /// GetGenericInterfaceImplementation(assembly, typeof(IResourceService&lt;&gt;), typeof(Article), typeof(Guid));
+        /// </code>
+        /// </example>
         public static (Type implementation, Type registrationInterface) GetGenericInterfaceImplementation(Assembly assembly, Type openGenericInterfaceType, params Type[] genericInterfaceArguments)
         {
             foreach (var type in assembly.GetTypes())
@@ -71,16 +94,33 @@ public static (Type implementation, Type registrationInterface) GetGenericInterf
             return (null, null);
         }
 
-        public static IEnumerable<Type> GetDerivedGenericTypes(Assembly assembly, Type openGenericType, Type genericArgument)
+        /// <summary>
+        /// Get all derivitives of the concrete, generic type.
+        /// </summary>
+        /// <param name="assembly">The assembly to search</param>
+        /// <param name="openGenericType">The open generic type, e.g. `typeof(ResourceDefinition&lt;&gt;)`</param>
+        /// <param name="genericArguments">Parameters to the generic type</param>
+        /// <example>
+        /// <code>
+        /// GetDerivedGenericTypes(assembly, typeof(ResourceDefinition<>), typeof(Article))
+        /// </code>
+        /// </example>
+        public static IEnumerable<Type> GetDerivedGenericTypes(Assembly assembly, Type openGenericType, params Type[] genericArguments)
         {
-            var genericType = openGenericType.MakeGenericType(genericArgument);
-            foreach (var type in assembly.GetTypes())
-            {
-                if (genericType.IsAssignableFrom(type))
-                    yield return type;
-            }
+            var genericType = openGenericType.MakeGenericType(genericArguments);
+            return GetDerivedTypes(assembly, genericType);
         }
 
+        /// <summary>
+        /// Get all derivitives of the specified type.
+        /// </summary>
+        /// <param name="assembly">The assembly to search</param>
+        /// <param name="openGenericType">The inherited type</param>
+        /// <example>
+        /// <code>
+        /// GetDerivedGenericTypes(assembly, typeof(DbContext))
+        /// </code>
+        /// </example>
         public static IEnumerable<Type> GetDerivedTypes(Assembly assembly, Type inheritedType)
         {
             foreach (var type in assembly.GetTypes())
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index f1cecab65d..7ec6a0bf87 100755
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <VersionPrefix>2.4.0</VersionPrefix>
+    <VersionPrefix>3.0.0</VersionPrefix>
     <TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
     <AssemblyName>JsonApiDotNetCore</AssemblyName>
     <PackageId>JsonApiDotNetCore</PackageId>

From 87a071f12ab72fc319282ce61b392fd4aad9f386 Mon Sep 17 00:00:00 2001
From: Jared Nance <jaredcnance@gmail.com>
Date: Sat, 11 Aug 2018 21:55:34 -0700
Subject: [PATCH 227/227] add documentation

---
 src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs | 4 ++++
 src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
index 6c836cdaca..ba71dbce06 100644
--- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs
@@ -195,6 +195,10 @@ public IContextGraphBuilder AddDbContext<T>() where T : DbContext
 
         private string GetResourceNameFromDbSetProperty(PropertyInfo property, Type resourceType)
         {
+            // this check is actually duplicated in the DefaultResourceNameFormatter
+            // however, we perform it here so that we allow class attributes to be prioritized over
+            // the DbSet attribute. Eventually, the DbSet attribute should be deprecated.
+            //
             // check the class definition first
             // [Resource("models"] public class Model : Identifiable { /* ... */ }
             if (resourceType.GetCustomAttribute(typeof(ResourceAttribute)) is ResourceAttribute classResourceAttribute)
diff --git a/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs b/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
index c67852620e..57baca0901 100644
--- a/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
+++ b/src/JsonApiDotNetCore/Graph/IResourceNameFormatter.cs
@@ -35,6 +35,8 @@ public string FormatResourceName(Type type)
         {
             try
             {
+                // check the class definition first
+                // [Resource("models"] public class Model : Identifiable { /* ... */ }
                 if (type.GetCustomAttribute(typeof(ResourceAttribute)) is ResourceAttribute attribute)
                     return attribute.ResourceName;