Skip to content

Commit 19d997c

Browse files
author
Bart Koelman
authored
Merge pull request #966 from json-api-dotnet/controller-type
Use controller type instead of name when mapping endpoints to resources
2 parents 31f21e8 + 6b11df5 commit 19d997c

File tree

5 files changed

+36
-17
lines changed

5 files changed

+36
-17
lines changed

src/JsonApiDotNetCore/Middleware/IControllerResourceMapping.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ namespace JsonApiDotNetCore.Middleware
88
public interface IControllerResourceMapping
99
{
1010
/// <summary>
11-
/// Get the associated resource type for the provided controller name.
11+
/// Get the associated resource type for the provided controller type.
1212
/// </summary>
13-
Type GetResourceTypeForController(string controllerName);
13+
Type GetResourceTypeForController(Type controllerType);
1414
}
1515
}

src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using JsonApiDotNetCore.Serialization.Objects;
1515
using Microsoft.AspNetCore.Http;
1616
using Microsoft.AspNetCore.Mvc;
17+
using Microsoft.AspNetCore.Mvc.Controllers;
1718
using Microsoft.AspNetCore.Routing;
1819
using Microsoft.Extensions.Primitives;
1920
using Newtonsoft.Json;
@@ -47,7 +48,7 @@ public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMappin
4748

4849
RouteValueDictionary routeValues = httpContext.GetRouteData().Values;
4950

50-
ResourceContext primaryResourceContext = CreatePrimaryResourceContext(routeValues, controllerResourceMapping, resourceContextProvider);
51+
ResourceContext primaryResourceContext = CreatePrimaryResourceContext(httpContext, controllerResourceMapping, resourceContextProvider);
5152

5253
if (primaryResourceContext != null)
5354
{
@@ -77,14 +78,16 @@ public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMappin
7778
await _next(httpContext);
7879
}
7980

80-
private static ResourceContext CreatePrimaryResourceContext(RouteValueDictionary routeValues, IControllerResourceMapping controllerResourceMapping,
81+
private static ResourceContext CreatePrimaryResourceContext(HttpContext httpContext, IControllerResourceMapping controllerResourceMapping,
8182
IResourceContextProvider resourceContextProvider)
8283
{
83-
string controllerName = (string)routeValues["controller"];
84+
Endpoint endpoint = httpContext.GetEndpoint();
85+
var controllerActionDescriptor = endpoint?.Metadata.GetMetadata<ControllerActionDescriptor>();
8486

85-
if (controllerName != null)
87+
if (controllerActionDescriptor != null)
8688
{
87-
Type resourceType = controllerResourceMapping.GetResourceTypeForController(controllerName);
89+
Type controllerType = controllerActionDescriptor.ControllerTypeInfo;
90+
Type resourceType = controllerResourceMapping.GetResourceTypeForController(controllerType);
8891

8992
if (resourceType != null)
9093
{

src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class JsonApiRoutingConvention : IJsonApiRoutingConvention
3434
private readonly IJsonApiOptions _options;
3535
private readonly IResourceContextProvider _resourceContextProvider;
3636
private readonly HashSet<string> _registeredTemplates = new HashSet<string>();
37-
private readonly Dictionary<string, ResourceContext> _registeredResources = new Dictionary<string, ResourceContext>();
37+
private readonly Dictionary<Type, ResourceContext> _resourceContextPerControllerTypeMap = new Dictionary<Type, ResourceContext>();
3838

3939
public JsonApiRoutingConvention(IJsonApiOptions options, IResourceContextProvider resourceContextProvider)
4040
{
@@ -46,11 +46,11 @@ public JsonApiRoutingConvention(IJsonApiOptions options, IResourceContextProvide
4646
}
4747

4848
/// <inheritdoc />
49-
public Type GetResourceTypeForController(string controllerName)
49+
public Type GetResourceTypeForController(Type controllerType)
5050
{
51-
ArgumentGuard.NotNullNorEmpty(controllerName, nameof(controllerName));
51+
ArgumentGuard.NotNull(controllerType, nameof(controllerType));
5252

53-
if (_registeredResources.TryGetValue(controllerName, out ResourceContext resourceContext))
53+
if (_resourceContextPerControllerTypeMap.TryGetValue(controllerType, out ResourceContext resourceContext))
5454
{
5555
return resourceContext.ResourceType;
5656
}
@@ -77,7 +77,7 @@ public void Apply(ApplicationModel application)
7777

7878
if (resourceContext != null)
7979
{
80-
_registeredResources.Add(controller.ControllerName, resourceContext);
80+
_resourceContextPerControllerTypeMap.Add(controller.ControllerType, resourceContext);
8181
}
8282
}
8383
}
@@ -112,7 +112,7 @@ private bool IsRoutingConventionEnabled(ControllerModel controller)
112112
/// </summary>
113113
private string TemplateFromResource(ControllerModel model)
114114
{
115-
if (_registeredResources.TryGetValue(model.ControllerName, out ResourceContext resourceContext))
115+
if (_resourceContextPerControllerTypeMap.TryGetValue(model.ControllerType, out ResourceContext resourceContext))
116116
{
117117
string template = $"{_options.Namespace}/{resourceContext.PublicName}";
118118

test/UnitTests/Middleware/JsonApiMiddlewareTests.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
using System;
22
using System.IO;
33
using System.Linq;
4+
using System.Reflection;
45
using System.Threading.Tasks;
56
using JsonApiDotNetCore.Configuration;
67
using JsonApiDotNetCore.Middleware;
78
using JsonApiDotNetCore.Resources.Annotations;
89
using Microsoft.AspNetCore.Http;
910
using Microsoft.AspNetCore.Http.Features;
11+
using Microsoft.AspNetCore.Mvc.Controllers;
1012
using Moq;
1113
using Moq.Language;
1214
using Xunit;
@@ -96,7 +98,7 @@ private InvokeConfiguration GetConfiguration(string path, string resourceName =
9698

9799
const string forcedNamespace = "api/v1";
98100
var mockMapping = new Mock<IControllerResourceMapping>();
99-
mockMapping.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny<string>())).Returns(typeof(string));
101+
mockMapping.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny<Type>())).Returns(typeof(string));
100102

101103
Mock<IJsonApiOptions> mockOptions = CreateMockOptions(forcedNamespace);
102104
Mock<IResourceGraph> mockGraph = CreateMockResourceGraph(resourceName, relType != null);
@@ -151,7 +153,13 @@ private static DefaultHttpContext CreateHttpContext(string path, bool isRelation
151153
}
152154

153155
context.Features.Set<IRouteValuesFeature>(feature);
154-
context.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(), null));
156+
157+
var controllerActionDescriptor = new ControllerActionDescriptor
158+
{
159+
ControllerTypeInfo = (TypeInfo)typeof(object)
160+
};
161+
162+
context.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(controllerActionDescriptor), null));
155163
return context;
156164
}
157165

test/UnitTests/Middleware/JsonApiRequestTests.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
using System;
22
using System.Linq;
3+
using System.Reflection;
34
using System.Threading.Tasks;
45
using FluentAssertions;
56
using JsonApiDotNetCore.Configuration;
67
using JsonApiDotNetCore.Middleware;
78
using JsonApiDotNetCoreExample.Models;
89
using Microsoft.AspNetCore.Http;
910
using Microsoft.AspNetCore.Http.Features;
11+
using Microsoft.AspNetCore.Mvc.Controllers;
1012
using Microsoft.Extensions.Logging.Abstractions;
1113
using Moq;
1214
using Xunit;
@@ -46,7 +48,7 @@ public async Task Sets_request_properties_correctly(string requestMethod, string
4648

4749
var controllerResourceMappingMock = new Mock<IControllerResourceMapping>();
4850

49-
controllerResourceMappingMock.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny<string>())).Returns(typeof(Article));
51+
controllerResourceMappingMock.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny<Type>())).Returns(typeof(Article));
5052

5153
var httpContext = new DefaultHttpContext();
5254
SetupRoutes(httpContext, requestMethod, requestPath);
@@ -98,7 +100,13 @@ private static void SetupRoutes(HttpContext httpContext, string requestMethod, s
98100
}
99101

100102
httpContext.Features.Set<IRouteValuesFeature>(feature);
101-
httpContext.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(), null));
103+
104+
var controllerActionDescriptor = new ControllerActionDescriptor
105+
{
106+
ControllerTypeInfo = (TypeInfo)typeof(object)
107+
};
108+
109+
httpContext.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(controllerActionDescriptor), null));
102110
}
103111
}
104112
}

0 commit comments

Comments
 (0)