From 624a5ed522e8e32a97fb1ba61e25d2302a5abfed Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 15 May 2018 14:41:02 -0700 Subject: [PATCH] Fix ActionMethodExecutor incorrectly setting DeclaredType on ObjectResult Fixes #7782 --- .../Internal/ActionMethodExecutor.cs | 2 +- .../Internal/ActionMethodExecutorTest.cs | 6 ++ .../XmlOutputFormatterTests.cs | 86 ++++++++++++++++++- .../DataContractSerializerController.cs | 17 ++++ .../Controllers/XmlSerializerController.cs | 13 +++ 5 files changed, 122 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ActionMethodExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ActionMethodExecutor.cs index 92b6335887..28541b3e55 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ActionMethodExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ActionMethodExecutor.cs @@ -201,7 +201,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal { // Async method returning awaitable-of-nonvoid var returnValue = await executor.ExecuteAsync(controller, arguments); - var actionResult = ConvertToActionResult(mapper, returnValue, executor.MethodReturnType); + var actionResult = ConvertToActionResult(mapper, returnValue, executor.AsyncResultType); return actionResult; } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ActionMethodExecutorTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ActionMethodExecutorTest.cs index b79a948e7c..6cd343dcd6 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ActionMethodExecutorTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ActionMethodExecutorTest.cs @@ -79,6 +79,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal var result = Assert.IsType(valueTask.Result); Assert.NotNull(result.Value); Assert.IsType(result.Value); + Assert.Equal(typeof(TestModel), result.DeclaredType); } [Fact] @@ -97,6 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal var result = Assert.IsType(valueTask.Result); Assert.NotNull(result.Value); Assert.IsType(result.Value); + Assert.Equal(typeof(TestModel), result.DeclaredType); } [Fact] @@ -115,6 +117,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal var result = Assert.IsType(valueTask.Result); Assert.NotNull(result.Value); Assert.IsType(result.Value); + Assert.Equal(typeof(object), result.DeclaredType); } [Fact] @@ -199,6 +202,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal var result = Assert.IsType(valueTask.Result); Assert.NotNull(result.Value); Assert.IsType(result.Value); + Assert.Equal(typeof(TestModel), result.DeclaredType); } [Fact] @@ -217,6 +221,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal var result = Assert.IsType(valueTask.Result); Assert.NotNull(result.Value); Assert.IsType(result.Value); + Assert.Equal(typeof(object), result.DeclaredType); } [Fact] @@ -251,6 +256,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal var result = Assert.IsType(valueTask.Result); Assert.NotNull(result.Value); Assert.IsType(result.Value); + Assert.Equal(typeof(TestModel), result.DeclaredType); } [Fact] diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/XmlOutputFormatterTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/XmlOutputFormatterTests.cs index fb4102d2c0..35e406ac6a 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/XmlOutputFormatterTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/XmlOutputFormatterTests.cs @@ -145,5 +145,89 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests // Assert Assert.Equal(HttpStatusCode.NotAcceptable, response.StatusCode); } + + // Xml-based formatters are sensitive to ObjectResult.DeclaredType of the result. A couple of + // tests to verify we don't regress these. + [Fact] + public async Task XmlSerializerFormatter_WorksForActionsReturningTaskOfDummyClass() + { + // Arrange + var request = new HttpRequestMessage( + HttpMethod.Post, + "http://localhost/XmlSerializer/GetTaskOfDummyClass"); + request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/xml")); + + // Act + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + XmlAssert.Equal( + "10", + await response.Content.ReadAsStringAsync()); + } + + [Fact] + public async Task XmlSerializerFormatter_WorksForActionsReturningDummyClassAsTaskOfObject() + { + // Arrange + var request = new HttpRequestMessage( + HttpMethod.Post, + "http://localhost/XmlSerializer/GetTaskOfDummyClassAsObject"); + request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/xml")); + + // Act + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + XmlAssert.Equal( + "10", + await response.Content.ReadAsStringAsync()); + } + + [Fact] + public async Task XmlSerializerOutputFormatter_WorksForActionsReturningTaskOfPerson() + { + // Arrange + var request = new HttpRequestMessage( + HttpMethod.Post, + "http://localhost/DataContractSerializer/GetTaskOfPerson?name=HelloWorld"); + request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/xml")); + + // Act + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + XmlAssert.Equal( + "" + + "HelloWorld", + await response.Content.ReadAsStringAsync()); + } + + [Fact] + public async Task XmlSerializerOutputFormatter_WorksForActionsReturningPersonAsTaskOfObject() + { + // Arrange + var request = new HttpRequestMessage( + HttpMethod.Post, + "http://localhost/DataContractSerializer/GetTaskOfPersonAsObject?name=HelloWorld"); + request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/xml")); + + // Act + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + XmlAssert.Equal( + "" + + "HelloWorld", + await response.Content.ReadAsStringAsync()); + } } -} \ No newline at end of file +} diff --git a/test/WebSites/FormatterWebSite/Controllers/DataContractSerializerController.cs b/test/WebSites/FormatterWebSite/Controllers/DataContractSerializerController.cs index 1a04d327b2..0eaab3d11b 100644 --- a/test/WebSites/FormatterWebSite/Controllers/DataContractSerializerController.cs +++ b/test/WebSites/FormatterWebSite/Controllers/DataContractSerializerController.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Formatters; @@ -31,5 +32,21 @@ namespace FormatterWebSite // DataContractSerializer should pick up this output. return new Person(name); } + + [HttpPost] + public Task GetTaskOfPerson(string name) + { + // The XmlSerializer should skip and the + // DataContractSerializer should pick up this output. + return Task.FromResult(new Person(name)); + } + + [HttpPost] + public Task GetTaskOfPersonAsObject(string name) + { + // The XmlSerializer should skip and the + // DataContractSerializer should pick up this output. + return Task.FromResult(new Person(name)); + } } } \ No newline at end of file diff --git a/test/WebSites/FormatterWebSite/Controllers/XmlSerializerController.cs b/test/WebSites/FormatterWebSite/Controllers/XmlSerializerController.cs index beef850e73..0fffe773ee 100644 --- a/test/WebSites/FormatterWebSite/Controllers/XmlSerializerController.cs +++ b/test/WebSites/FormatterWebSite/Controllers/XmlSerializerController.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Formatters; @@ -45,5 +46,17 @@ namespace FormatterWebSite { "Hello", "World" } }; } + + [HttpPost] + public Task GetTaskOfDummyClass() + { + return Task.FromResult(new DummyClass { SampleInt = 10 }); + } + + [HttpPost] + public Task GetTaskOfDummyClassAsObject() + { + return Task.FromResult(new DummyClass { SampleInt = 10 }); + } } } \ No newline at end of file