24
24
using JsonApiDotNetCore . Serialization . Server . Builders ;
25
25
using JsonApiDotNetCore . Serialization . Server ;
26
26
using JsonApiDotNetCore . Serialization . Client ;
27
- using JsonApiDotNetCore . Controllers ;
27
+ using Microsoft . Extensions . DependencyInjection . Extensions ;
28
28
29
29
namespace JsonApiDotNetCore . Extensions
30
30
{
31
31
// ReSharper disable once InconsistentNaming
32
32
public static class IServiceCollectionExtensions
33
33
{
34
34
static private readonly Action < JsonApiOptions > _noopConfig = opt => { } ;
35
- static private JsonApiOptions _options { get { return new JsonApiOptions ( ) ; } }
36
35
public static IServiceCollection AddJsonApi < TContext > ( this IServiceCollection services ,
37
36
IMvcCoreBuilder mvcBuilder = null )
38
37
where TContext : DbContext
@@ -48,25 +47,20 @@ public static IServiceCollection AddJsonApi<TContext>(this IServiceCollection se
48
47
/// <param name="configureAction"></param>
49
48
/// <returns></returns>
50
49
public static IServiceCollection AddJsonApi < TContext > ( this IServiceCollection services ,
51
- Action < JsonApiOptions > configureAction ,
50
+ Action < JsonApiOptions > configureOptions ,
52
51
IMvcCoreBuilder mvcBuilder = null )
53
52
where TContext : DbContext
54
53
{
55
- var options = _options ;
54
+ var options = new JsonApiOptions ( ) ;
56
55
// add basic Mvc functionality
57
56
mvcBuilder = mvcBuilder ?? services . AddMvcCore ( ) ;
58
- // set standard options
59
- configureAction ( options ) ;
60
-
57
+ // configures JsonApiOptions;
58
+ configureOptions ( options ) ;
61
59
// ResourceGraphBuilder should not be exposed on JsonApiOptions.
62
60
// Instead, ResourceGraphBuilder should consume JsonApiOptions
63
-
64
61
// build the resource graph using ef core DbContext
65
62
options . BuildResourceGraph ( builder => builder . AddDbContext < TContext > ( ) ) ;
66
-
67
- // add JsonApi fitlers and serializer
68
- mvcBuilder . AddMvcOptions ( opt => AddMvcOptions ( opt , options ) ) ;
69
-
63
+ ConfigureMvc ( services , mvcBuilder , options ) ;
70
64
// register services
71
65
AddJsonApiInternals < TContext > ( services , options ) ;
72
66
return services ;
@@ -83,13 +77,12 @@ public static IServiceCollection AddJsonApi(this IServiceCollection services,
83
77
Action < JsonApiOptions > configureOptions ,
84
78
IMvcCoreBuilder mvcBuilder = null )
85
79
{
86
- var options = _options ;
80
+ var options = new JsonApiOptions ( ) ;
81
+ // add basic Mvc functionality
87
82
mvcBuilder = mvcBuilder ?? services . AddMvcCore ( ) ;
83
+ // configures JsonApiOptions;
88
84
configureOptions ( options ) ;
89
-
90
- // add JsonApi fitlers and serializer
91
- mvcBuilder . AddMvcOptions ( opt => AddMvcOptions ( opt , options ) ) ;
92
-
85
+ ConfigureMvc ( services , mvcBuilder , options ) ;
93
86
// register services
94
87
AddJsonApiInternals ( services , options ) ;
95
88
return services ;
@@ -107,22 +100,29 @@ public static IServiceCollection AddJsonApi(this IServiceCollection services,
107
100
Action < ServiceDiscoveryFacade > autoDiscover ,
108
101
IMvcCoreBuilder mvcBuilder = null )
109
102
{
110
- var options = _options ;
103
+ var options = new JsonApiOptions ( ) ;
104
+ // add basic Mvc functionality
111
105
mvcBuilder = mvcBuilder ?? services . AddMvcCore ( ) ;
106
+ // configures JsonApiOptions;
112
107
configureOptions ( options ) ;
113
-
114
108
// build the resource graph using auto discovery.
115
109
var facade = new ServiceDiscoveryFacade ( services , options . ResourceGraphBuilder ) ;
116
110
autoDiscover ( facade ) ;
117
-
118
- // add JsonApi fitlers and serializer
119
- mvcBuilder . AddMvcOptions ( opt => AddMvcOptions ( opt , options ) ) ;
120
-
111
+ ConfigureMvc ( services , mvcBuilder , options ) ;
121
112
// register services
122
113
AddJsonApiInternals ( services , options ) ;
123
114
return services ;
124
115
}
125
116
117
+ private static void ConfigureMvc ( IServiceCollection services , IMvcCoreBuilder mvcBuilder , JsonApiOptions options )
118
+ {
119
+ // add JsonApi filters and serializers
120
+ mvcBuilder . AddMvcOptions ( opt => AddMvcOptions ( opt , options ) ) ;
121
+ // register services that allow user to override behaviour that is configured on startup, like routing conventions
122
+ AddStartupConfigurationServices ( services , options ) ;
123
+ var intermediateProvider = services . BuildServiceProvider ( ) ;
124
+ mvcBuilder . AddMvcOptions ( opt => opt . Conventions . Insert ( 0 , intermediateProvider . GetRequiredService < IJsonApiRoutingConvention > ( ) ) ) ;
125
+ }
126
126
127
127
private static void AddMvcOptions ( MvcOptions options , JsonApiOptions config )
128
128
{
@@ -143,11 +143,20 @@ public static void AddJsonApiInternals<TContext>(
143
143
AddJsonApiInternals ( services , jsonApiOptions ) ;
144
144
}
145
145
146
+ /// <summary>
147
+ /// Adds services to the container that need to be retrieved with an intermediate provider during Startup.
148
+ /// </summary>
149
+ private static void AddStartupConfigurationServices ( this IServiceCollection services , JsonApiOptions jsonApiOptions )
150
+ {
151
+ services . AddSingleton < IJsonApiOptions > ( jsonApiOptions ) ;
152
+ services . TryAddSingleton < IResourceNameFormatter > ( new KebabCaseFormatter ( ) ) ;
153
+ services . TryAddSingleton < IJsonApiRoutingConvention , DefaultRoutingConvention > ( ) ;
154
+ }
155
+
146
156
public static void AddJsonApiInternals (
147
157
this IServiceCollection services ,
148
158
JsonApiOptions jsonApiOptions )
149
159
{
150
-
151
160
var graph = jsonApiOptions . ResourceGraph ?? jsonApiOptions . ResourceGraphBuilder . Build ( ) ;
152
161
153
162
if ( graph . UsesDbContext == false )
@@ -183,14 +192,12 @@ public static void AddJsonApiInternals(
183
192
services . AddScoped ( typeof ( IResourceService < > ) , typeof ( EntityResourceService < > ) ) ;
184
193
services . AddScoped ( typeof ( IResourceService < , > ) , typeof ( EntityResourceService < , > ) ) ;
185
194
186
- services . AddSingleton < IJsonApiOptions > ( jsonApiOptions ) ;
187
195
services . AddSingleton < ILinksConfiguration > ( jsonApiOptions ) ;
188
196
services . AddSingleton ( graph ) ;
189
197
services . AddSingleton < IHttpContextAccessor , HttpContextAccessor > ( ) ;
190
198
services . AddSingleton < IContextEntityProvider > ( graph ) ;
191
199
services . AddScoped < ICurrentRequest , CurrentRequest > ( ) ;
192
- services . AddScoped < IScopedServiceProvider , RequestScopedServiceProvider > ( ) ;
193
- services . AddScoped < JsonApiRouteHandler > ( ) ;
200
+ services . AddScoped < IScopedServiceProvider , RequestScopedServiceProvider > ( ) ;
194
201
services . AddScoped < IJsonApiWriter , JsonApiWriter > ( ) ;
195
202
services . AddScoped < IJsonApiReader , JsonApiReader > ( ) ;
196
203
services . AddScoped < IGenericProcessorFactory , GenericProcessorFactory > ( ) ;
@@ -273,7 +280,6 @@ public static void SerializeAsJsonApi(this MvcOptions options, JsonApiOptions js
273
280
{
274
281
options . InputFormatters . Insert ( 0 , new JsonApiInputFormatter ( ) ) ;
275
282
options . OutputFormatters . Insert ( 0 , new JsonApiOutputFormatter ( ) ) ;
276
- options . Conventions . Insert ( 0 , new DasherizedRoutingConvention ( jsonApiOptions . Namespace ) ) ;
277
283
}
278
284
279
285
/// <summary>
0 commit comments