diff --git a/src/JsonApiDotNetCore/Middleware/IControllerResourceMapping.cs b/src/JsonApiDotNetCore/Middleware/IControllerResourceMapping.cs index 28719247a9..6f4a8beb7a 100644 --- a/src/JsonApiDotNetCore/Middleware/IControllerResourceMapping.cs +++ b/src/JsonApiDotNetCore/Middleware/IControllerResourceMapping.cs @@ -8,8 +8,8 @@ namespace JsonApiDotNetCore.Middleware public interface IControllerResourceMapping { /// - /// Get the associated resource type for the provided controller name. + /// Get the associated resource type for the provided controller type. /// - Type GetResourceTypeForController(string controllerName); + Type GetResourceTypeForController(Type controllerType); } } diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs b/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs index 85796ef54f..0043e4064d 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiMiddleware.cs @@ -14,6 +14,7 @@ using JsonApiDotNetCore.Serialization.Objects; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Primitives; using Newtonsoft.Json; @@ -47,7 +48,7 @@ public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMappin RouteValueDictionary routeValues = httpContext.GetRouteData().Values; - ResourceContext primaryResourceContext = CreatePrimaryResourceContext(routeValues, controllerResourceMapping, resourceContextProvider); + ResourceContext primaryResourceContext = CreatePrimaryResourceContext(httpContext, controllerResourceMapping, resourceContextProvider); if (primaryResourceContext != null) { @@ -77,14 +78,16 @@ public async Task InvokeAsync(HttpContext httpContext, IControllerResourceMappin await _next(httpContext); } - private static ResourceContext CreatePrimaryResourceContext(RouteValueDictionary routeValues, IControllerResourceMapping controllerResourceMapping, + private static ResourceContext CreatePrimaryResourceContext(HttpContext httpContext, IControllerResourceMapping controllerResourceMapping, IResourceContextProvider resourceContextProvider) { - string controllerName = (string)routeValues["controller"]; + Endpoint endpoint = httpContext.GetEndpoint(); + var controllerActionDescriptor = endpoint?.Metadata.GetMetadata(); - if (controllerName != null) + if (controllerActionDescriptor != null) { - Type resourceType = controllerResourceMapping.GetResourceTypeForController(controllerName); + Type controllerType = controllerActionDescriptor.ControllerTypeInfo; + Type resourceType = controllerResourceMapping.GetResourceTypeForController(controllerType); if (resourceType != null) { diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs b/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs index c9abf109c1..80e2aa5dce 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiRoutingConvention.cs @@ -34,7 +34,7 @@ public class JsonApiRoutingConvention : IJsonApiRoutingConvention private readonly IJsonApiOptions _options; private readonly IResourceContextProvider _resourceContextProvider; private readonly HashSet _registeredTemplates = new HashSet(); - private readonly Dictionary _registeredResources = new Dictionary(); + private readonly Dictionary _resourceContextPerControllerTypeMap = new Dictionary(); public JsonApiRoutingConvention(IJsonApiOptions options, IResourceContextProvider resourceContextProvider) { @@ -46,11 +46,11 @@ public JsonApiRoutingConvention(IJsonApiOptions options, IResourceContextProvide } /// - public Type GetResourceTypeForController(string controllerName) + public Type GetResourceTypeForController(Type controllerType) { - ArgumentGuard.NotNullNorEmpty(controllerName, nameof(controllerName)); + ArgumentGuard.NotNull(controllerType, nameof(controllerType)); - if (_registeredResources.TryGetValue(controllerName, out ResourceContext resourceContext)) + if (_resourceContextPerControllerTypeMap.TryGetValue(controllerType, out ResourceContext resourceContext)) { return resourceContext.ResourceType; } @@ -77,7 +77,7 @@ public void Apply(ApplicationModel application) if (resourceContext != null) { - _registeredResources.Add(controller.ControllerName, resourceContext); + _resourceContextPerControllerTypeMap.Add(controller.ControllerType, resourceContext); } } } @@ -112,7 +112,7 @@ private bool IsRoutingConventionEnabled(ControllerModel controller) /// private string TemplateFromResource(ControllerModel model) { - if (_registeredResources.TryGetValue(model.ControllerName, out ResourceContext resourceContext)) + if (_resourceContextPerControllerTypeMap.TryGetValue(model.ControllerType, out ResourceContext resourceContext)) { string template = $"{_options.Namespace}/{resourceContext.PublicName}"; diff --git a/test/UnitTests/Middleware/JsonApiMiddlewareTests.cs b/test/UnitTests/Middleware/JsonApiMiddlewareTests.cs index 9df692d51c..0f331b0a6f 100644 --- a/test/UnitTests/Middleware/JsonApiMiddlewareTests.cs +++ b/test/UnitTests/Middleware/JsonApiMiddlewareTests.cs @@ -1,12 +1,14 @@ using System; using System.IO; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Resources.Annotations; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Mvc.Controllers; using Moq; using Moq.Language; using Xunit; @@ -96,7 +98,7 @@ private InvokeConfiguration GetConfiguration(string path, string resourceName = const string forcedNamespace = "api/v1"; var mockMapping = new Mock(); - mockMapping.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny())).Returns(typeof(string)); + mockMapping.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny())).Returns(typeof(string)); Mock mockOptions = CreateMockOptions(forcedNamespace); Mock mockGraph = CreateMockResourceGraph(resourceName, relType != null); @@ -151,7 +153,13 @@ private static DefaultHttpContext CreateHttpContext(string path, bool isRelation } context.Features.Set(feature); - context.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(), null)); + + var controllerActionDescriptor = new ControllerActionDescriptor + { + ControllerTypeInfo = (TypeInfo)typeof(object) + }; + + context.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(controllerActionDescriptor), null)); return context; } diff --git a/test/UnitTests/Middleware/JsonApiRequestTests.cs b/test/UnitTests/Middleware/JsonApiRequestTests.cs index 092e0d4ad3..7bd2ffcbb5 100644 --- a/test/UnitTests/Middleware/JsonApiRequestTests.cs +++ b/test/UnitTests/Middleware/JsonApiRequestTests.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using FluentAssertions; using JsonApiDotNetCore.Configuration; @@ -7,6 +8,7 @@ using JsonApiDotNetCoreExample.Models; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -46,7 +48,7 @@ public async Task Sets_request_properties_correctly(string requestMethod, string var controllerResourceMappingMock = new Mock(); - controllerResourceMappingMock.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny())).Returns(typeof(Article)); + controllerResourceMappingMock.Setup(mapping => mapping.GetResourceTypeForController(It.IsAny())).Returns(typeof(Article)); var httpContext = new DefaultHttpContext(); SetupRoutes(httpContext, requestMethod, requestPath); @@ -98,7 +100,13 @@ private static void SetupRoutes(HttpContext httpContext, string requestMethod, s } httpContext.Features.Set(feature); - httpContext.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(), null)); + + var controllerActionDescriptor = new ControllerActionDescriptor + { + ControllerTypeInfo = (TypeInfo)typeof(object) + }; + + httpContext.SetEndpoint(new Endpoint(null, new EndpointMetadataCollection(controllerActionDescriptor), null)); } } }