1+ using System ;
2+ using System . Collections ;
13using System . Collections . Generic ;
24using System . Linq ;
5+ using System . Reflection ;
36using System . Threading . Tasks ;
47using AutoMapper ;
58using JsonApiDotNetCore . Data ;
1013
1114namespace JsonApiDotNetCore . Services
1215{
13- public class MappingResourceService < TDto , TEntity > :
14- MappingResourceService < TDto , TEntity , int > ,
15- IResourceService < TDto >
16- where TDto : class , IIdentifiable < int >
16+ public class MappingResourceService < TResource , TEntity >
17+ : MappingResourceService < TResource , TEntity , int > ,
18+ IResourceService < TResource >
19+ where TResource : class , IIdentifiable < int >
1720 where TEntity : class , IIdentifiable < int >
1821 {
1922 public MappingResourceService (
@@ -25,8 +28,9 @@ public MappingResourceService(
2528 { }
2629 }
2730
28- public class MappingResourceService < TDto , TEntity , TId > : IResourceService < TDto , TId >
29- where TDto : class , IIdentifiable < TId >
31+ public class MappingResourceService < TResource , TEntity , TId >
32+ : IResourceService < TResource , TId >
33+ where TResource : class , IIdentifiable < TId >
3034 where TEntity : class , IIdentifiable < TId >
3135 {
3236 private readonly IJsonApiContext _jsonApiContext ;
@@ -42,11 +46,11 @@ public MappingResourceService(
4246 {
4347 _jsonApiContext = jsonApiContext ;
4448 _entities = entityRepository ;
45- _logger = loggerFactory . CreateLogger < MappingResourceService < TDto , TEntity , TId > > ( ) ;
49+ _logger = loggerFactory . CreateLogger < MappingResourceService < TResource , TEntity , TId > > ( ) ;
4650 _mapper = mapper ;
4751 }
4852
49- public virtual async Task < IEnumerable < TDto > > GetAsync ( )
53+ public virtual async Task < IEnumerable < TResource > > GetAsync ( )
5054 {
5155 var entities = _entities . Get ( ) ;
5256
@@ -63,90 +67,92 @@ public virtual async Task<IEnumerable<TDto>> GetAsync()
6367 return pagedEntities ;
6468 }
6569
66- public virtual async Task < TDto > GetAsync ( TId id )
70+ public virtual async Task < TResource > GetAsync ( TId id )
6771 {
68- TDto entity ;
72+ TResource dto ;
6973 if ( ShouldIncludeRelationships ( ) )
70- entity = await GetWithRelationshipsAsync ( id ) ;
74+ dto = await GetWithRelationshipsAsync ( id ) ;
7175 else
72- entity = _mapper . Map < TDto > ( await _entities . GetAsync ( id ) ) ;
73- return entity ;
76+ {
77+ TEntity entity = await _entities . GetAsync ( id ) ;
78+ dto = _mapper . Map < TResource > ( entity ) ;
79+ }
80+ return dto ;
7481 }
7582
7683 private bool ShouldIncludeRelationships ( )
7784 => ( _jsonApiContext . QuerySet ? . IncludedRelationships != null && _jsonApiContext . QuerySet . IncludedRelationships . Count > 0 ) ;
7885
79- private async Task < TDto > GetWithRelationshipsAsync ( TId id )
86+ private async Task < TResource > GetWithRelationshipsAsync ( TId id )
8087 {
8188 var query = _entities . Get ( ) . Where ( e => e . Id . Equals ( id ) ) ;
8289 _jsonApiContext . QuerySet . IncludedRelationships . ForEach ( r =>
8390 {
8491 query = _entities . Include ( query , r ) ;
8592 } ) ;
8693 var value = await _entities . FirstOrDefaultAsync ( query ) ;
87- return _mapper . Map < TDto > ( value ) ;
94+ return _mapper . Map < TResource > ( value ) ;
8895 }
8996
9097 public virtual async Task < object > GetRelationshipsAsync ( TId id , string relationshipName )
9198 => await GetRelationshipAsync ( id , relationshipName ) ;
9299
93100 public virtual async Task < object > GetRelationshipAsync ( TId id , string relationshipName )
94101 {
95- relationshipName = _jsonApiContext . ContextGraph
96- . GetRelationshipName < TDto > ( relationshipName ) ;
97-
98- if ( relationshipName == null )
99- throw new JsonApiException ( 422 , "Relationship name not specified." ) ;
100- if ( _logger . IsEnabled ( LogLevel . Trace ) )
101- {
102- _logger . LogTrace ( $ "Looking up '{ relationshipName } '...") ;
103- }
104-
105102 var entity = await _entities . GetAndIncludeAsync ( id , relationshipName ) ;
106103 // TODO: it would be better if we could distinguish whether or not the relationship was not found,
107104 // vs the relationship not being set on the instance of T
108105 if ( entity == null )
106+ {
109107 throw new JsonApiException ( 404 , $ "Relationship { relationshipName } not found.") ;
108+ }
110109
111- var relationship = _jsonApiContext . ContextGraph
112- . GetRelationship ( entity , relationshipName ) ;
113-
110+ var resource = _mapper . Map < TResource > ( entity ) ;
111+ var relationship = _jsonApiContext . ContextGraph . GetRelationship ( resource , relationshipName ) ;
114112 return relationship ;
115113 }
116114
117- public virtual async Task < TDto > CreateAsync ( TDto entity )
115+ public virtual async Task < TResource > CreateAsync ( TResource resource )
118116 {
119- var createdEntity = await _entities . CreateAsync ( _mapper . Map < TEntity > ( entity ) ) ;
120- return _mapper . Map < TDto > ( createdEntity ) ;
117+ var entity = _mapper . Map < TEntity > ( resource ) ;
118+ entity = await _entities . CreateAsync ( entity ) ;
119+ return _mapper . Map < TResource > ( entity ) ;
121120 }
122121
123- public virtual async Task < TDto > UpdateAsync ( TId id , TDto entity )
122+ public virtual async Task < TResource > UpdateAsync ( TId id , TResource resource )
124123 {
125- var updatedEntity = await _entities . UpdateAsync ( id , _mapper . Map < TEntity > ( entity ) ) ;
126- return _mapper . Map < TDto > ( updatedEntity ) ;
124+ var entity = _mapper . Map < TEntity > ( resource ) ;
125+ entity = await _entities . UpdateAsync ( id , entity ) ;
126+ return _mapper . Map < TResource > ( entity ) ;
127127 }
128128
129129 public virtual async Task UpdateRelationshipsAsync ( TId id , string relationshipName , List < DocumentData > relationships )
130130 {
131- relationshipName = _jsonApiContext . ContextGraph
132- . GetRelationshipName < TDto > ( relationshipName ) ;
133-
134- if ( relationshipName == null )
135- throw new JsonApiException ( 422 , "Relationship name not specified." ) ;
136-
137131 var entity = await _entities . GetAndIncludeAsync ( id , relationshipName ) ;
138-
139132 if ( entity == null )
133+ {
140134 throw new JsonApiException ( 404 , $ "Entity with id { id } could not be found.") ;
135+ }
141136
142137 var relationship = _jsonApiContext . ContextGraph
143- . GetContextEntity ( typeof ( TDto ) )
138+ . GetContextEntity ( typeof ( TResource ) )
144139 . Relationships
145- . FirstOrDefault ( r => r . InternalRelationshipName == relationshipName ) ;
140+ . FirstOrDefault ( r => r . PublicRelationshipName == relationshipName ) ;
141+ var relationshipType = relationship . Type ;
142+
143+ // update relationship type with internalname
144+ var entityProperty = typeof ( TEntity ) . GetProperty ( relationship . InternalRelationshipName ) ;
145+ if ( entityProperty == null )
146+ {
147+ throw new JsonApiException ( 404 , $ "Property { relationship . InternalRelationshipName } could not be found on entity.") ;
148+ }
149+ relationship . Type = relationship . IsHasMany ? entityProperty . PropertyType . GetGenericArguments ( ) [ 0 ] : entityProperty . PropertyType ;
146150
147151 var relationshipIds = relationships . Select ( r => r ? . Id ? . ToString ( ) ) ;
148152
149153 await _entities . UpdateRelationshipsAsync ( entity , relationship , relationshipIds ) ;
154+
155+ relationship . Type = relationshipType ;
150156 }
151157
152158 public virtual async Task < bool > DeleteAsync ( TId id )
@@ -171,18 +177,18 @@ protected virtual IQueryable<TEntity> ApplySortAndFilterQuery(IQueryable<TEntity
171177 return entities ;
172178 }
173179
174- protected virtual async Task < IEnumerable < TDto > > ApplyPageQueryAsync ( IQueryable < TEntity > entities )
180+ protected virtual async Task < IEnumerable < TResource > > ApplyPageQueryAsync ( IQueryable < TEntity > entities )
175181 {
176182 var pageManager = _jsonApiContext . PageManager ;
177183 if ( ! pageManager . IsPaginated )
178- return _mapper . Map < IEnumerable < TDto > > ( await _entities . ToListAsync ( entities ) ) ;
184+ return _mapper . Map < IEnumerable < TResource > > ( await _entities . ToListAsync ( entities ) ) ;
179185
180186 if ( _logger ? . IsEnabled ( LogLevel . Information ) == true )
181187 {
182188 _logger ? . LogInformation ( $ "Applying paging query. Fetching page { pageManager . CurrentPage } with { pageManager . PageSize } entities") ;
183189 }
184190
185- return _mapper . Map < IEnumerable < TDto > > ( await _entities . PageAsync ( entities , pageManager . PageSize , pageManager . CurrentPage ) ) ;
191+ return _mapper . Map < IEnumerable < TResource > > ( await _entities . PageAsync ( entities , pageManager . PageSize , pageManager . CurrentPage ) ) ;
186192 }
187193
188194 protected virtual IQueryable < TEntity > IncludeRelationships ( IQueryable < TEntity > entities , List < string > relationships )
0 commit comments