Skip to content

Decoupling context #554

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1f8a3f8
feat: started work on decoupling
May 3, 2019
88235e8
feat: add total record count
May 3, 2019
1a94a49
feat: green tests, new managers
May 13, 2019
ab78ad2
feat: changed startup
May 17, 2019
5da1a86
feat: most annoying commit of my life, rewriting dozens of controllers
May 17, 2019
494f6eb
feat: rename: QueryManager -> RequestManager, deeper seperation of co…
May 23, 2019
77a2ae9
feat: removed JsonApiContext dependency from controller, fixed namesp…
May 24, 2019
94615f8
feat: decoupled controllers
May 24, 2019
4a53c00
chore: renamed resourcegraphbuilder, took out some extensions, made …
May 27, 2019
0547fe5
chore: merge + refactor to allow for old code
Jul 2, 2019
afb02f2
feat: json api context decoupling mroe and more
Jul 2, 2019
fa954be
fix: merge with master
Aug 15, 2019
2be340b
chore: readded solutions
Aug 15, 2019
6796295
feat: upgrading to 2.2, setting contextentity in middleware
Sep 2, 2019
0d21254
fix: removed outdated authorization test
Sep 3, 2019
ab02766
fix: requestmeta tests
Sep 3, 2019
7246ca9
fix: some acceptance tests
Sep 5, 2019
c177659
fix: pagination
Sep 5, 2019
857b8a9
fix: total records in meta
Sep 6, 2019
4eec35a
feat: introduced JsonApiActionFilter
Sep 6, 2019
d672e8e
fix: more tests
Sep 9, 2019
0704cc6
feat: decoupled deserializer and serializer
Sep 26, 2019
5745c44
chore: remove / cleanup old serializers
Sep 26, 2019
b679f07
chore: remove operation services
Sep 26, 2019
12d43ed
tests: unit tests client/server (de)serializers
Sep 26, 2019
03f4b7a
chore: various edits to run tests
Sep 26, 2019
39742a7
fix: rm dasherized resolver
Sep 26, 2019
3721b7d
chore: remove JsonApiContext and corresponding interface
Sep 27, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
<NetCoreAppVersion>netcoreapp2.0</NetCoreAppVersion>
<NetStandardVersion>netstandard2.0</NetStandardVersion>

<AspNetCoreVersion>2.1.0</AspNetCoreVersion>
<AspNetCoreVersion>2.*</AspNetCoreVersion>

<MicrosoftLoggingVersion>2.1.0</MicrosoftLoggingVersion>
<MicrosoftConfigurationVersion>2.1.0</MicrosoftConfigurationVersion>
<MicrosoftOptionsVersion>2.1.0</MicrosoftOptionsVersion>
<MicrosoftLoggingVersion>2.*</MicrosoftLoggingVersion>
<MicrosoftConfigurationVersion>2.*</MicrosoftConfigurationVersion>
<MicrosoftOptionsVersion>2.*</MicrosoftOptionsVersion>

<EFCoreVersion>2.1.0</EFCoreVersion>
<EFCoreToolsVersion>2.1.0</EFCoreToolsVersion>
<EFCoreVersion>2.*</EFCoreVersion>
<EFCoreToolsVersion>2.*</EFCoreToolsVersion>

<NpgsqlVersion>4.0.0</NpgsqlVersion>
<NpgsqlPostgreSQLVersion>2.1.0</NpgsqlPostgreSQLVersion>
Expand Down
376 changes: 188 additions & 188 deletions JsonApiDotnetCore.sln

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ See [the documentation](https://json-api-dotnet.github.io/#/) for detailed usage

```csharp
public class Article : Identifiable
{
{
[Attr("name")]
public string Name { get; set; }
}
Expand Down Expand Up @@ -91,7 +91,7 @@ Running tests locally requires access to a postgresql database.
If you have docker installed, this can be propped up via:

```bash
docker run --rm --name jsonapi-dotnet-core-testing -e POSTGRES_DB=JsonApiDotNetCoreExample -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres
docker run --rm --name jsonapi-dotnet-core-testing -e POSTGRES_DB=JsonApiDotNetCoreExample -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres
```

And then to run the tests:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;
using System;

namespace Benchmarks.LinkBuilder
{
[MarkdownExporter, SimpleJob(launchCount : 3, warmupCount : 10, targetCount : 20), MemoryDiagnoser]
[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";
Expand All @@ -14,7 +15,7 @@ public class LinkBuilder_GetNamespaceFromPath_Benchmarks
public void UsingSplit() => GetNamespaceFromPath_BySplitting(PATH, ENTITY_NAME);

[Benchmark]
public void Current() => GetNameSpaceFromPath_Current(PATH, ENTITY_NAME);
public void Current() => GetNameSpaceFromPathCurrent(PATH, ENTITY_NAME);

public static string GetNamespaceFromPath_BySplitting(string path, string entityName)
{
Expand All @@ -32,7 +33,38 @@ public static string GetNamespaceFromPath_BySplitting(string path, string entity
return nSpace;
}

public static string GetNameSpaceFromPath_Current(string path, string entityName)
=> JsonApiDotNetCore.Builders.LinkBuilder.GetNamespaceFromPath(path, entityName);
public static string GetNameSpaceFromPathCurrent(string path, string entityName)
{

var entityNameSpan = entityName.AsSpan();
var pathSpan = path.AsSpan();
const char delimiter = '/';
for (var i = 0; i < pathSpan.Length; i++)
{
if (pathSpan[i].Equals(delimiter))
{
var nextPosition = i + 1;
if (pathSpan.Length > i + entityNameSpan.Length)
{
var possiblePathSegment = pathSpan.Slice(nextPosition, entityNameSpan.Length);
if (entityNameSpan.SequenceEqual(possiblePathSegment))
{
// check to see if it's the last position in the string
// or if the next character is a /
var lastCharacterPosition = nextPosition + entityNameSpan.Length;

if (lastCharacterPosition == pathSpan.Length || pathSpan.Length >= lastCharacterPosition + 2 && pathSpan[lastCharacterPosition].Equals(delimiter))
{
return pathSpan.Slice(0, i).ToString();
}
}
}
}
}

return string.Empty;


}
}
}
6 changes: 3 additions & 3 deletions benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Running;
using Benchmarks.JsonApiContext;
using Benchmarks.LinkBuilder;
using Benchmarks.Query;
Expand All @@ -9,8 +9,8 @@ namespace Benchmarks {
class Program {
static void Main(string[] args) {
var switcher = new BenchmarkSwitcher(new[] {
typeof(JsonApiDeserializer_Benchmarks),
typeof(JsonApiSerializer_Benchmarks),
typeof(JsonApideserializer_Benchmarks),
//typeof(JsonApiSerializer_Benchmarks),
typeof(QueryParser_Benchmarks),
typeof(LinkBuilder_GetNamespaceFromPath_Benchmarks),
typeof(ContainsMediaTypeParameters_Benchmarks),
Expand Down
11 changes: 6 additions & 5 deletions benchmarks/Query/QueryParser_Benchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using BenchmarkDotNet.Attributes.Jobs;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Internal;
using JsonApiDotNetCore.Managers.Contracts;
using JsonApiDotNetCore.Models;
using JsonApiDotNetCore.Services;
using Microsoft.AspNetCore.Http.Internal;
Expand All @@ -21,14 +22,14 @@ public class QueryParser_Benchmarks {
private const string DESCENDING_SORT = "-" + ATTRIBUTE;

public QueryParser_Benchmarks() {
var controllerContextMock = new Mock<IControllerContext>();
controllerContextMock.Setup(m => m.RequestEntity).Returns(new ContextEntity {
var requestMock = new Mock<IRequestContext>();
requestMock.Setup(m => m.GetRequestResource()).Returns(new ContextEntity {
Attributes = new List<AttrAttribute> {
new AttrAttribute(ATTRIBUTE, ATTRIBUTE)
}
});
var options = new JsonApiOptions();
_queryParser = new BenchmarkFacade(controllerContextMock.Object, options);
_queryParser = new BenchmarkFacade(requestMock.Object, options);
}

[Benchmark]
Expand Down Expand Up @@ -58,8 +59,8 @@ private void Run(int iterations, Action action) {
// this facade allows us to expose and micro-benchmark protected methods
private class BenchmarkFacade : QueryParser {
public BenchmarkFacade(
IControllerContext controllerContext,
JsonApiOptions options) : base(controllerContext, options) { }
IRequestContext requestManager,
JsonApiOptions options) : base(requestManager, options) { }

public void _ParseSortParameters(string value) => base.ParseSortParameters(value);
}
Expand Down
22 changes: 14 additions & 8 deletions benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
using BenchmarkDotNet.Attributes.Exporters;
using JsonApiDotNetCore.Builders;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Internal.Generics;
using JsonApiDotNetCore.Managers.Contracts;
using JsonApiDotNetCore.Models;
using JsonApiDotNetCore.Serialization;
using JsonApiDotNetCore.Serialization.Contracts;

using JsonApiDotNetCore.Services;
using Moq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace Benchmarks.Serialization {
namespace Benchmarks.Serialization
{
[MarkdownExporter]
public class JsonApiDeserializer_Benchmarks {
public class JsonApideserializer_Benchmarks {
private const string TYPE_NAME = "simple-types";
private static readonly string Content = JsonConvert.SerializeObject(new Document {
Data = new ResourceObject {
Expand All @@ -29,28 +32,31 @@ public class JsonApiDeserializer_Benchmarks {
}
});

private readonly JsonApiDeSerializer _jsonApiDeSerializer;
private readonly JsonApideserializer _jsonApideserializer;

public JsonApiDeserializer_Benchmarks() {
public JsonApideserializer_Benchmarks() {
var resourceGraphBuilder = new ResourceGraphBuilder();
resourceGraphBuilder.AddResource<SimpleType>(TYPE_NAME);
var resourceGraph = resourceGraphBuilder.Build();
var requestManagerMock = new Mock<IRequestContext>();

requestManagerMock.Setup(m => m.GetUpdatedAttributes()).Returns(new Dictionary<AttrAttribute, object>());

var jsonApiContextMock = new Mock<IJsonApiContext>();
jsonApiContextMock.SetupAllProperties();
jsonApiContextMock.Setup(m => m.ResourceGraph).Returns(resourceGraph);
jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary<AttrAttribute, object>());
jsonApiContextMock.Setup(m => m.RequestManager.GetUpdatedAttributes()).Returns(new Dictionary<AttrAttribute, object>());

var jsonApiOptions = new JsonApiOptions();
jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);


_jsonApiDeSerializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
_jsonApideserializer = new JsonApideserializer(jsonApiContextMock.Object, requestManagerMock.Object);
}

[Benchmark]
public object DeserializeSimpleObject() => _jsonApiDeSerializer.Deserialize<SimpleType>(Content);
public object DeserializeSimpleObject() => _jsonApideserializer.Deserialize<SimpleType>(Content);

private class SimpleType : Identifiable {
[Attr("name")]
Expand Down
100 changes: 51 additions & 49 deletions benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,51 @@
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Exporters;
using JsonApiDotNetCore.Builders;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Internal.Generics;
using JsonApiDotNetCore.Models;
using JsonApiDotNetCore.Serialization;
using JsonApiDotNetCore.Services;
using Moq;
using Newtonsoft.Json.Serialization;

namespace Benchmarks.Serialization {
[MarkdownExporter]
public class JsonApiSerializer_Benchmarks {
private const string TYPE_NAME = "simple-types";
private static readonly SimpleType Content = new SimpleType();

private readonly JsonApiSerializer _jsonApiSerializer;

public JsonApiSerializer_Benchmarks() {
var resourceGraphBuilder = new ResourceGraphBuilder();
resourceGraphBuilder.AddResource<SimpleType>(TYPE_NAME);
var resourceGraph = resourceGraphBuilder.Build();

var jsonApiContextMock = new Mock<IJsonApiContext>();
jsonApiContextMock.SetupAllProperties();
jsonApiContextMock.Setup(m => m.ResourceGraph).Returns(resourceGraph);
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 SerializeSimpleObject() => _jsonApiSerializer.Serialize(Content);

private class SimpleType : Identifiable {
[Attr("name")]
public string Name { get; set; }
}
}
}
//using System.Collections.Generic;
//using BenchmarkDotNet.Attributes;
//using BenchmarkDotNet.Attributes.Exporters;
//using JsonApiDotNetCore.Builders;
//using JsonApiDotNetCore.Configuration;
//using JsonApiDotNetCore.Internal.Generics;
//using JsonApiDotNetCore.Models;
//using JsonApiDotNetCore.Serialization;
using JsonApiDotNetCore.Serialization.Contracts;

//using JsonApiDotNetCore.Services;
//using Moq;
//using Newtonsoft.Json.Serialization;

//namespace Benchmarks.Serialization {
// [MarkdownExporter]
// public class JsonApiSerializer_Benchmarks {
// private const string TYPE_NAME = "simple-types";
// private static readonly SimpleType Content = new SimpleType();

// private readonly JsonApiSerializer _jsonApiSerializer;

// public JsonApiSerializer_Benchmarks() {
// var resourceGraphBuilder = new ResourceGraphBuilder();
// resourceGraphBuilder.AddResource<SimpleType>(TYPE_NAME);
// var resourceGraph = resourceGraphBuilder.Build();

// var jsonApiContextMock = new Mock<IJsonApiContext>();
// jsonApiContextMock.SetupAllProperties();
// jsonApiContextMock.Setup(m => m.ResourceGraph).Returns(resourceGraph);
// 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 SerializeSimpleObject() => _jsonApiSerializer.Serialize(Content);

// private class SimpleType : Identifiable {
// [Attr("name")]
// public string Name { get; set; }
// }
// }
//}
3 changes: 3 additions & 0 deletions docs/obsoletes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# For v5

* Anything to do with JsonApiContext, make it internal and fix anything related to it.
5 changes: 5 additions & 0 deletions markdownlint.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"MD033": {
"allowed_elements": [ "p", "img", "p" ]
}
}
11 changes: 7 additions & 4 deletions src/Examples/GettingStarted/Controllers/ArticlesController.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using GettingStarted.Models;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers;
using JsonApiDotNetCore.Internal.Contracts;
using JsonApiDotNetCore.Services;

namespace GettingStarted
{
public class ArticlesController : JsonApiController<Article>
{
public ArticlesController(
IJsonApiContext jsonApiContext,
IResourceService<Article> resourceService)
: base(jsonApiContext, resourceService)
IJsonApiOptions jsonApiOptions,
IResourceGraph resourceGraph,
IResourceService<Article> resourceService)
: base(jsonApiOptions, resourceGraph, resourceService)
{ }
}
}
}
11 changes: 7 additions & 4 deletions src/Examples/GettingStarted/Controllers/PeopleController.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using GettingStarted.Models;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers;
using JsonApiDotNetCore.Internal.Contracts;
using JsonApiDotNetCore.Services;

namespace GettingStarted
{
public class PeopleController : JsonApiController<Person>
{
public PeopleController(
IJsonApiContext jsonApiContext,
IResourceService<Person> resourceService)
: base(jsonApiContext, resourceService)
IJsonApiOptions jsonApiOptions,
IResourceGraph resourceGraph,
IResourceService<Person> resourceService)
: base(jsonApiOptions, resourceGraph, resourceService)
{ }
}
}
}
6 changes: 3 additions & 3 deletions src/Examples/GettingStarted/GettingStarted.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(EFCoreVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="$(EFCoreVersion)" />
</ItemGroup>

</Project>
1 change: 0 additions & 1 deletion src/Examples/GettingStarted/Models/Article.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ public class Article : Identifiable
{
[Attr]
public string Title { get; set; }

[HasOne]
public Person Author { get; set; }
public int AuthorId { get; set; }
Expand Down
Loading