From f204aa4430d8e2768040c2b627d299f52afd8d55 Mon Sep 17 00:00:00 2001 From: David W <1511024+marabooy@users.noreply.github.com> Date: Thu, 11 Nov 2021 19:35:33 +0300 Subject: [PATCH] Migrate https://github.com/OData/WebApi/pull/2512 to WebApi 8. --- .../Query/EnableQueryAttribute.cs | 7 +- .../Query/EnableQueryAttributeTests.cs | 89 +++++++++++++++++++ 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNetCore.OData/Query/EnableQueryAttribute.cs b/src/Microsoft.AspNetCore.OData/Query/EnableQueryAttribute.cs index cf673463c..9eb7c11d4 100644 --- a/src/Microsoft.AspNetCore.OData/Query/EnableQueryAttribute.cs +++ b/src/Microsoft.AspNetCore.OData/Query/EnableQueryAttribute.cs @@ -20,6 +20,7 @@ using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.OData.Common; using Microsoft.AspNetCore.OData.Edm; using Microsoft.AspNetCore.OData.Extensions; @@ -224,8 +225,8 @@ public override void OnActionExecuted(ActionExecutedContext actionExecutedContex { // actionExecutedContext.Result might also indicate a status code that has not yet // been applied to the result; make sure it's also successful. - StatusCodeResult statusCodeResult = actionExecutedContext.Result as StatusCodeResult; - if (statusCodeResult == null || IsSuccessStatusCode(statusCodeResult.StatusCode)) + IStatusCodeActionResult statusCodeResult = actionExecutedContext.Result as IStatusCodeActionResult; + if (statusCodeResult?.StatusCode == null || IsSuccessStatusCode(statusCodeResult.StatusCode.Value)) { ObjectResult responseContent = actionExecutedContext.Result as ObjectResult; if (responseContent != null) @@ -730,7 +731,7 @@ private static bool ContainsAutoSelectExpandProperty(object responseValue, IQuer ODataPath path = request.ODataFeature().Path; IEdmProperty pathProperty = null; - IEdmStructuredType pathStructuredType = null; + IEdmStructuredType pathStructuredType = null; if (path != null) { (pathProperty, pathStructuredType, _) = path.GetPropertyAndStructuredTypeFromPath(); diff --git a/test/Microsoft.AspNetCore.OData.Tests/Query/EnableQueryAttributeTests.cs b/test/Microsoft.AspNetCore.OData.Tests/Query/EnableQueryAttributeTests.cs index f23cecdb4..51edc6b96 100644 --- a/test/Microsoft.AspNetCore.OData.Tests/Query/EnableQueryAttributeTests.cs +++ b/test/Microsoft.AspNetCore.OData.Tests/Query/EnableQueryAttributeTests.cs @@ -15,9 +15,19 @@ using System.Net.Http; using System.Reflection; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.OData.Extensions; using Microsoft.AspNetCore.OData.Query; using Microsoft.AspNetCore.OData.TestCommon; using Microsoft.AspNetCore.OData.Tests.Commons; +using Microsoft.AspNetCore.OData.Tests.Extensions; +using Microsoft.AspNetCore.OData.Tests.Models; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; using Microsoft.OData; using Microsoft.OData.Edm; using Microsoft.OData.UriParser; @@ -234,6 +244,85 @@ public void OnActionExecuted_Throws_Null_Context() ExceptionAssert.ThrowsArgumentNull(() => new EnableQueryAttribute().OnActionExecuted(null), "actionExecutedContext"); } + [Fact] + public void OnActionExecuted_HandlesStatusCodesCorrectly() + { + // Arrange + HttpContext httpContext = new DefaultHttpContext(); + httpContext.Request.Method = "Get"; + ActionDescriptor actionDescriptor = new ActionDescriptor(); + ActionContext actionContext = new ActionContext(httpContext, new RouteData(), actionDescriptor); + + ActionExecutedContext context = new ActionExecutedContext(actionContext, new List(), "someController"); + context.Result = new ObjectResult(new { Error = "Error", Message = "Message" }) { StatusCode = 500 }; + + EnableQueryAttribute attribute = new EnableQueryAttribute(); + + // Act and Assert + ExceptionAssert.DoesNotThrow(() => attribute.OnActionExecuted(context)); + } + + [Fact] + public void OnActionExecuted_HandlesRequestsNormally() + { + IEdmModel model = new CustomersModelWithInheritance().Model; + + var request = RequestFactory.Create("Get", "http://localhost/Customers", opt => opt.AddRouteComponents(model).Filter()); + + ODataUriParser parser = new ODataUriParser(model, new Uri("Customers", UriKind.Relative)); + HttpContext httpContext = request.HttpContext; + + Assert.NotNull(httpContext.RequestServices); + + httpContext.Request.Method = "Get"; + request.Configure("odata", model, parser.ParsePath()); + ActionDescriptor actionDescriptor = CreateDescriptors("CustomersController", typeof(CustomersController)) + .First(descriptor => descriptor.ActionName.StartsWith("Get", StringComparison.OrdinalIgnoreCase)); + ActionContext actionContext = new ActionContext(httpContext, new RouteData(), actionDescriptor); + + ActionExecutedContext context = new ActionExecutedContext(actionContext, new List(), new CustomersController()); + context.Result = new ObjectResult(new List() { new Customer { Id = 1, Name = "John Doe" } }) { StatusCode = 200 }; + + EnableQueryAttribute attribute = new EnableQueryAttribute(); + + // Act and Assert + ExceptionAssert.DoesNotThrow(() => attribute.OnActionExecuted(context)); + var result = context.Result as ObjectResult; + Assert.NotNull(context.Result); + } + + /// + /// Initializes a new instance of the [Http]ControllerDescriptor class. + /// + /// A new instance of the [Http]ControllerDescriptor class. + private static IEnumerable CreateDescriptors(string name, Type controllerType) + { + // Create descriptors. Search for non-public methods to pick up public methods in nested classes + // as controllers are usually a nested class for the test class ad by default, this are marked private. + List descriptors = new List(); + IEnumerable methods = controllerType.GetTypeInfo().DeclaredMethods; + foreach (MethodInfo methodInfo in methods) + { + ControllerActionDescriptor descriptor = new ControllerActionDescriptor(); + descriptor.ControllerName = name; + descriptor.ControllerTypeInfo = controllerType.GetTypeInfo(); + descriptor.ActionName = methodInfo.Name; + descriptor.DisplayName = methodInfo.Name; + descriptor.MethodInfo = methodInfo; + descriptor.Parameters = methodInfo + .GetParameters() + .Select(p => new ParameterDescriptor + { + Name = p.Name, + ParameterType = p.ParameterType + }) + .ToList(); + descriptors.Add(descriptor); + } + + return descriptors; + } + #if NETCORE // Following functionality is only supported in NetCore. [Fact] public void OnActionExecuting_Throws_Null_Context()