Skip to content

Commit d672e8e

Browse files
Maurits MoeysMaurits Moeys
Maurits Moeys
authored and
Maurits Moeys
committed
fix: more tests
1 parent 4eec35a commit d672e8e

File tree

26 files changed

+207
-117
lines changed

26 files changed

+207
-117
lines changed

benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using BenchmarkDotNet.Attributes.Exporters;
55
using JsonApiDotNetCore.Builders;
66
using JsonApiDotNetCore.Configuration;
7+
using JsonApiDotNetCore.Managers.Contracts;
78
using JsonApiDotNetCore.Models;
89
using JsonApiDotNetCore.Serialization;
910
using JsonApiDotNetCore.Services;
@@ -35,6 +36,9 @@ public JsonApiDeserializer_Benchmarks() {
3536
var resourceGraphBuilder = new ResourceGraphBuilder();
3637
resourceGraphBuilder.AddResource<SimpleType>(TYPE_NAME);
3738
var resourceGraph = resourceGraphBuilder.Build();
39+
var requestManagerMock = new Mock<IRequestManager>();
40+
41+
requestManagerMock.Setup(m => m.GetUpdatedAttributes()).Returns(new Dictionary<AttrAttribute, object>());
3842

3943
var jsonApiContextMock = new Mock<IJsonApiContext>();
4044
jsonApiContextMock.SetupAllProperties();
@@ -46,7 +50,7 @@ public JsonApiDeserializer_Benchmarks() {
4650
jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
4751

4852

49-
_jsonApiDeSerializer = new JsonApiDeSerializer(jsonApiContextMock.Object);
53+
_jsonApiDeSerializer = new JsonApiDeSerializer(jsonApiContextMock.Object, requestManagerMock.Object);
5054
}
5155

5256
[Benchmark]

src/Examples/GettingStarted/Startup.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@ public void ConfigureServices(IServiceCollection services)
2020
options.UseSqlite("Data Source=sample.db");
2121
});
2222

23-
var mvcCoreBuilder = services.AddMvcCore();
23+
var mvcBuilder = services.AddMvcCore();
2424
services.AddJsonApi(
2525
options => options.Namespace = "api",
26-
mvcCoreBuilder,
27-
discover => discover.AddCurrentAssembly());
26+
discover => discover.AddCurrentAssembly(), mvcBuilder);
2827
}
2928

3029
public void Configure(IApplicationBuilder app, IHostingEnvironment env, SampleDbContext context)

src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
9292
public DbSet<ArticleTag> ArticleTags { get; set; }
9393
public DbSet<IdentifiableArticleTag> IdentifiableArticleTags { get; set; }
9494
public DbSet<Tag> Tags { get; set; }
95+
96+
9597
}
98+
99+
96100
}

src/Examples/JsonApiDotNetCoreExample/Resources/ArticleResource.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
using JsonApiDotNetCore.Models;
66
using JsonApiDotNetCore.Hooks;
77
using JsonApiDotNetCoreExample.Models;
8-
using Microsoft.Extensions.Logging;
9-
using System.Security.Principal;
108
using JsonApiDotNetCore.Internal.Contracts;
119

1210
namespace JsonApiDotNetCoreExample.Resources

src/Examples/JsonApiDotNetCoreExample/Services/CustomArticleService.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using JsonApiDotNetCore.Configuration;
22
using JsonApiDotNetCore.Data;
3+
using JsonApiDotNetCore.Hooks;
34
using JsonApiDotNetCore.Internal;
45
using JsonApiDotNetCore.Internal.Contracts;
56
using JsonApiDotNetCore.Managers.Contracts;
@@ -18,8 +19,9 @@ public CustomArticleService(
1819
IRequestManager queryManager,
1920
IPageManager pageManager,
2021
IResourceGraph resourceGraph,
22+
IResourceHookExecutor resourceHookExecutor = null,
2123
ILoggerFactory loggerFactory = null
22-
) : base(repository: repository, jsonApiOptions, queryManager, pageManager, resourceGraph:resourceGraph, loggerFactory)
24+
) : base(repository: repository, jsonApiOptions, queryManager, pageManager, resourceGraph:resourceGraph, loggerFactory, resourceHookExecutor)
2325
{ }
2426

2527
public override async Task<Article> GetAsync(int id)

src/Examples/JsonApiDotNetCoreExample/Startup.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
using Microsoft.EntityFrameworkCore;
88
using JsonApiDotNetCore.Extensions;
99
using System;
10-
using System.ComponentModel.Design;
11-
using JsonApiDotNetCoreExample.Models;
12-
using JsonApiDotNetCore.Services;
1310

1411
namespace JsonApiDotNetCoreExample
1512
{
@@ -32,7 +29,6 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
3229
{
3330
var loggerFactory = new LoggerFactory();
3431
loggerFactory.AddConsole(LogLevel.Warning);
35-
var mvcBuilder = services.AddMvcCore();
3632
services
3733
.AddSingleton<ILoggerFactory>(loggerFactory)
3834
.AddDbContext<AppDbContext>(options => options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Transient)
@@ -43,7 +39,6 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
4339
options.EnableResourceHooks = true;
4440
options.LoadDatabaseValues = true;
4541
},
46-
mvcBuilder,
4742
discovery => discovery.AddCurrentAssembly());
4843

4944
return services.BuildServiceProvider();

src/Examples/ReportsExample/Startup.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ public virtual void ConfigureServices(IServiceCollection services)
2727
var mvcBuilder = services.AddMvcCore();
2828
services.AddJsonApi(
2929
opt => opt.Namespace = "api",
30-
mvcBuilder,
31-
discovery => discovery.AddCurrentAssembly());
30+
discovery => discovery.AddCurrentAssembly(), mvcBuilder);
3231
}
3332

3433
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

src/Examples/ResourceEntitySeparationExample/Startup.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,19 @@ public virtual IServiceProvider ConfigureServices(IServiceCollection services)
4343
ServiceLifetime.Transient);
4444
services.AddScoped<IDbContextResolver, DbContextResolver<AppDbContext>>();
4545

46-
var mvcBuilder = services.AddMvcCore();
4746

4847
services.AddJsonApi(options => {
4948
options.Namespace = "api/v1";
5049
options.DefaultPageSize = 10;
5150
options.IncludeTotalRecordCount = true;
52-
options.BuildResourceGraph((builder) => {
51+
options.EnableResourceHooks = false; // not supported with ResourceEntitySeparation
52+
options.BuildResourceGraph((builder) =>
53+
{
5354
builder.AddResource<CourseResource>("courses");
5455
builder.AddResource<DepartmentResource>("departments");
5556
builder.AddResource<StudentResource>("students");
5657
});
57-
}, mvcBuilder);
58+
});
5859

5960
services.AddAutoMapper();
6061
services.AddScoped<IResourceMapper, AutoMapperAdapter>();

src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
using System.Collections.Generic;
33
using JsonApiDotNetCore.Builders;
44
using JsonApiDotNetCore.Graph;
5-
using JsonApiDotNetCore.Internal;
65
using JsonApiDotNetCore.Internal.Contracts;
76
using JsonApiDotNetCore.Models;
87
using JsonApiDotNetCore.Serialization;
98
using Microsoft.EntityFrameworkCore;
109
using Newtonsoft.Json;
11-
using Newtonsoft.Json.Serialization;
1210

1311
namespace JsonApiDotNetCore.Configuration
1412
{
@@ -32,7 +30,7 @@ public class JsonApiOptions : IJsonApiOptions
3230
/// Whether or not stack traces should be serialized in Error objects
3331
/// </summary>
3432
public static bool DisableErrorStackTraces { get; set; }
35-
33+
3634
/// <summary>
3735
/// Whether or not source URLs should be serialized in Error objects
3836
/// </summary>

src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs

Lines changed: 77 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,52 +29,99 @@ namespace JsonApiDotNetCore.Extensions
2929
// ReSharper disable once InconsistentNaming
3030
public static class IServiceCollectionExtensions
3131
{
32-
public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services)
32+
static private readonly Action<JsonApiOptions> _noopConfig = opt => { };
33+
static private JsonApiOptions _options { get { return new JsonApiOptions(); } }
34+
public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services,
35+
IMvcCoreBuilder mvcBuilder = null)
3336
where TContext : DbContext
3437
{
35-
var mvcBuilder = services.AddMvcCore();
36-
return AddJsonApi<TContext>(services, opt => { }, mvcBuilder);
38+
return AddJsonApi<TContext>(services, _noopConfig, mvcBuilder);
3739
}
3840

39-
public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services, Action<JsonApiOptions> options)
41+
/// <summary>
42+
/// Enabling JsonApiDotNetCore using the EF Core DbContext to build the ResourceGraph.
43+
/// </summary>
44+
/// <typeparam name="TContext"></typeparam>
45+
/// <param name="services"></param>
46+
/// <param name="configureAction"></param>
47+
/// <returns></returns>
48+
public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection services,
49+
Action<JsonApiOptions> configureAction,
50+
IMvcCoreBuilder mvcBuilder = null)
4051
where TContext : DbContext
4152
{
42-
var mvcBuilder = services.AddMvcCore();
43-
return AddJsonApi<TContext>(services, options, mvcBuilder);
53+
var options = _options;
54+
// add basic Mvc functionality
55+
mvcBuilder = mvcBuilder ?? services.AddMvcCore();
56+
// set standard options
57+
configureAction(options);
58+
59+
// ResourceGraphBuilder should not be exposed on JsonApiOptions.
60+
// Instead, ResourceGraphBuilder should consume JsonApiOptions
61+
62+
// build the resource graph using ef core DbContext
63+
options.BuildResourceGraph(builder => builder.AddDbContext<TContext>());
64+
65+
// add JsonApi fitlers and serializer
66+
mvcBuilder.AddMvcOptions(opt => AddMvcOptions(opt, options));
67+
68+
// register services
69+
AddJsonApiInternals<TContext>(services, options);
70+
return services;
4471
}
4572

46-
public static IServiceCollection AddJsonApi<TContext>(
47-
this IServiceCollection services,
48-
Action<JsonApiOptions> options,
49-
IMvcCoreBuilder mvcBuilder) where TContext : DbContext
73+
74+
/// <summary>
75+
/// Enabling JsonApiDotNetCore using manual declaration to build the ResourceGraph.
76+
/// </summary>
77+
/// <param name="services"></param>
78+
/// <param name="configureOptions"></param>
79+
/// <returns></returns>
80+
public static IServiceCollection AddJsonApi(this IServiceCollection services,
81+
Action<JsonApiOptions> configureOptions,
82+
IMvcCoreBuilder mvcBuilder = null)
5083
{
51-
var config = new JsonApiOptions();
52-
options(config);
53-
config.BuildResourceGraph(builder => builder.AddDbContext<TContext>());
54-
mvcBuilder.AddMvcOptions(opt => AddMvcOptions(opt, config));
55-
AddJsonApiInternals<TContext>(services, config);
84+
var options = _options;
85+
mvcBuilder = mvcBuilder ?? services.AddMvcCore();
86+
configureOptions(options);
87+
88+
// add JsonApi fitlers and serializer
89+
mvcBuilder.AddMvcOptions(opt => AddMvcOptions(opt, options));
90+
91+
// register services
92+
AddJsonApiInternals(services, options);
5693
return services;
5794
}
5895

59-
public static IServiceCollection AddJsonApi(
60-
this IServiceCollection services,
61-
Action<JsonApiOptions> configureOptions,
62-
IMvcCoreBuilder mvcBuilder,
63-
Action<ServiceDiscoveryFacade> autoDiscover = null)
96+
/// <summary>
97+
/// Enabling JsonApiDotNetCore using the EF Core DbContext to build the ResourceGraph.
98+
/// </summary>
99+
/// <param name="services"></param>
100+
/// <param name="configureOptions"></param>
101+
/// <param name="autoDiscover"></param>
102+
/// <returns></returns>
103+
public static IServiceCollection AddJsonApi(this IServiceCollection services,
104+
Action<JsonApiOptions> configureOptions,
105+
Action<ServiceDiscoveryFacade> autoDiscover,
106+
IMvcCoreBuilder mvcBuilder = null)
64107
{
65-
var config = new JsonApiOptions();
66-
configureOptions(config);
108+
var options = _options;
109+
mvcBuilder = mvcBuilder ?? services.AddMvcCore();
110+
configureOptions(options);
67111

68-
if (autoDiscover != null)
69-
{
70-
var facade = new ServiceDiscoveryFacade(services, config.ResourceGraphBuilder);
71-
autoDiscover(facade);
72-
}
73-
mvcBuilder.AddMvcOptions(opt => AddMvcOptions(opt, config));
74-
AddJsonApiInternals(services, config);
112+
// build the resource graph using auto discovery.
113+
var facade = new ServiceDiscoveryFacade(services, options.ResourceGraphBuilder);
114+
autoDiscover(facade);
115+
116+
// add JsonApi fitlers and serializer
117+
mvcBuilder.AddMvcOptions(opt => AddMvcOptions(opt, options));
118+
119+
// register services
120+
AddJsonApiInternals(services, options);
75121
return services;
76122
}
77123

124+
78125
private static void AddMvcOptions(MvcOptions options, JsonApiOptions config)
79126
{
80127
options.Filters.Add(typeof(JsonApiExceptionFilter));
@@ -144,7 +191,6 @@ public static void AddJsonApiInternals(
144191
services.AddScoped(typeof(IResourceService<,>), typeof(EntityResourceService<,>));
145192

146193
services.AddScoped<ILinkBuilder, LinkBuilder>();
147-
services.AddScoped<ITraversalHelper, TraversalHelper>();
148194
services.AddScoped<IRequestManager, RequestManager>();
149195
services.AddSingleton<IJsonApiOptions>(jsonApiOptions);
150196
services.AddScoped<IPageManager, PageManager>();
@@ -173,7 +219,7 @@ public static void AddJsonApiInternals(
173219
services.AddTransient(typeof(IResourceHookExecutor), typeof(ResourceHookExecutor));
174220
services.AddTransient<IHookExecutorHelper, HookExecutorHelper>();
175221
}
176-
services.AddTransient<IActionContextAccessor, ActionContextAccessor>();
222+
//services.AddTransient<IActionContextAccessor, ActionContextAccessor>();
177223

178224
services.AddScoped<IInverseRelationships, InverseRelationships>();
179225
}

src/JsonApiDotNetCore/Formatters/JsonApiReader.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Threading.Tasks;
55
using JsonApiDotNetCore.Internal;
6+
using JsonApiDotNetCore.Managers.Contracts;
67
using JsonApiDotNetCore.Models;
78
using JsonApiDotNetCore.Serialization;
89
using JsonApiDotNetCore.Services;
@@ -16,13 +17,13 @@ namespace JsonApiDotNetCore.Formatters
1617
public class JsonApiReader : IJsonApiReader
1718
{
1819
private readonly IJsonApiDeSerializer _deserializer;
19-
private readonly IJsonApiContext _jsonApiContext;
20+
private readonly IRequestManager _requestManager;
2021
private readonly ILogger<JsonApiReader> _logger;
2122

22-
public JsonApiReader(IJsonApiDeSerializer deSerializer, IJsonApiContext jsonApiContext, ILoggerFactory loggerFactory)
23+
public JsonApiReader(IJsonApiDeSerializer deSerializer, IRequestManager requestManager, ILoggerFactory loggerFactory)
2324
{
2425
_deserializer = deSerializer;
25-
_jsonApiContext = jsonApiContext;
26+
_requestManager = requestManager;
2627
_logger = loggerFactory.CreateLogger<JsonApiReader>();
2728
}
2829

@@ -40,7 +41,7 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
4041
var body = GetRequestBody(context.HttpContext.Request.Body);
4142

4243
object model = null;
43-
if (_jsonApiContext.IsRelationshipPath)
44+
if (_requestManager.IsRelationshipPath)
4445
{
4546
model = _deserializer.DeserializeRelationship(body);
4647
}

src/JsonApiDotNetCore/Hooks/ResourceHookExecutor.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,21 @@ namespace JsonApiDotNetCore.Hooks
1818
internal class ResourceHookExecutor : IResourceHookExecutor
1919
{
2020
public static readonly IdentifiableComparer Comparer = new IdentifiableComparer();
21-
internal readonly ITraversalHelper _traversalHelper;
2221
private readonly IRequestManager _requestManager;
2322
internal readonly IHookExecutorHelper _executorHelper;
2423
protected readonly IJsonApiContext _context;
2524
private readonly IResourceGraph _graph;
25+
private readonly TraversalHelper _traversalHelper;
2626

2727
public ResourceHookExecutor(
2828
IHookExecutorHelper helper,
29-
ITraversalHelper traversalHelper,
3029
IResourceGraph resourceGraph,
3130
IRequestManager requestManager)
3231
{
3332
_requestManager = requestManager;
3433
_executorHelper = helper;
3534
_graph = resourceGraph;
36-
_traversalHelper = traversalHelper;
35+
_traversalHelper = new TraversalHelper(resourceGraph, requestManager);
3736
}
3837

3938
/// <inheritdoc/>

src/JsonApiDotNetCore/Internal/ResourceGraph.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,19 @@ public RelationshipAttribute GetInverseRelationship(RelationshipAttribute relati
137137

138138
public ContextEntity GetEntityFromControllerName(string controllerName)
139139
{
140-
var resource = ControllerResourceMap.FirstOrDefault(cm => cm.ControllerName == controllerName)?.Resource;
141-
if (resource == null) return null;
142-
return Entities.First(e => e.EntityType == resource);
140+
141+
if (ControllerResourceMap.Any())
142+
{
143+
// Autodiscovery was used, so there is a well defined mapping between exposed resources and their associated controllers
144+
var resourceType = ControllerResourceMap.FirstOrDefault(cm => cm.ControllerName == controllerName)?.Resource;
145+
if (resourceType == null) return null;
146+
return Entities.First(e => e.EntityType == resourceType);
147+
148+
} else
149+
{
150+
// No autodiscovery: try to guess contextentity from controller name.
151+
return Entities.FirstOrDefault(e => e.EntityName.ToLower().Replace("-", "") == controllerName.ToLower());
152+
}
143153
}
144154
}
145155
}

0 commit comments

Comments
 (0)