Fix ActionMethodExecutor incorrectly setting DeclaredType on ObjectResult
Fixes #7782
This commit is contained in:
parent
c08b29beda
commit
984cd46c4d
|
|
@ -201,7 +201,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
{
|
{
|
||||||
// Async method returning awaitable-of-nonvoid
|
// Async method returning awaitable-of-nonvoid
|
||||||
var returnValue = await executor.ExecuteAsync(controller, arguments);
|
var returnValue = await executor.ExecuteAsync(controller, arguments);
|
||||||
var actionResult = ConvertToActionResult(mapper, returnValue, executor.MethodReturnType);
|
var actionResult = ConvertToActionResult(mapper, returnValue, executor.AsyncResultType);
|
||||||
return actionResult;
|
return actionResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
||||||
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
||||||
Assert.NotNull(result.Value);
|
Assert.NotNull(result.Value);
|
||||||
Assert.IsType<TestModel>(result.Value);
|
Assert.IsType<TestModel>(result.Value);
|
||||||
|
Assert.Equal(typeof(TestModel), result.DeclaredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -97,6 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
||||||
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
||||||
Assert.NotNull(result.Value);
|
Assert.NotNull(result.Value);
|
||||||
Assert.IsType<TestModel>(result.Value);
|
Assert.IsType<TestModel>(result.Value);
|
||||||
|
Assert.Equal(typeof(TestModel), result.DeclaredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -115,6 +117,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
||||||
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
||||||
Assert.NotNull(result.Value);
|
Assert.NotNull(result.Value);
|
||||||
Assert.IsType<TestModel>(result.Value);
|
Assert.IsType<TestModel>(result.Value);
|
||||||
|
Assert.Equal(typeof(object), result.DeclaredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -199,6 +202,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
||||||
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
||||||
Assert.NotNull(result.Value);
|
Assert.NotNull(result.Value);
|
||||||
Assert.IsType<TestModel>(result.Value);
|
Assert.IsType<TestModel>(result.Value);
|
||||||
|
Assert.Equal(typeof(TestModel), result.DeclaredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -217,6 +221,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
||||||
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
||||||
Assert.NotNull(result.Value);
|
Assert.NotNull(result.Value);
|
||||||
Assert.IsType<TestModel>(result.Value);
|
Assert.IsType<TestModel>(result.Value);
|
||||||
|
Assert.Equal(typeof(object), result.DeclaredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -251,6 +256,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Internal
|
||||||
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
var result = Assert.IsType<ObjectResult>(valueTask.Result);
|
||||||
Assert.NotNull(result.Value);
|
Assert.NotNull(result.Value);
|
||||||
Assert.IsType<TestModel>(result.Value);
|
Assert.IsType<TestModel>(result.Value);
|
||||||
|
Assert.Equal(typeof(TestModel), result.DeclaredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -145,5 +145,89 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(HttpStatusCode.NotAcceptable, response.StatusCode);
|
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(
|
||||||
|
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
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(
|
||||||
|
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
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(
|
||||||
|
"<Person xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns=\"http://schemas.datacontract.org/2004/07/FormatterWebSite\">" +
|
||||||
|
"<Name>HelloWorld</Name></Person>",
|
||||||
|
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(
|
||||||
|
"<Person xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns=\"http://schemas.datacontract.org/2004/07/FormatterWebSite\">" +
|
||||||
|
"<Name>HelloWorld</Name></Person>",
|
||||||
|
await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
|
|
@ -31,5 +32,21 @@ namespace FormatterWebSite
|
||||||
// DataContractSerializer should pick up this output.
|
// DataContractSerializer should pick up this output.
|
||||||
return new Person(name);
|
return new Person(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<Person> GetTaskOfPerson(string name)
|
||||||
|
{
|
||||||
|
// The XmlSerializer should skip and the
|
||||||
|
// DataContractSerializer should pick up this output.
|
||||||
|
return Task.FromResult(new Person(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<object> GetTaskOfPersonAsObject(string name)
|
||||||
|
{
|
||||||
|
// The XmlSerializer should skip and the
|
||||||
|
// DataContractSerializer should pick up this output.
|
||||||
|
return Task.FromResult<object>(new Person(name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
|
|
@ -45,5 +46,17 @@ namespace FormatterWebSite
|
||||||
{ "Hello", "World" }
|
{ "Hello", "World" }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<DummyClass> GetTaskOfDummyClass()
|
||||||
|
{
|
||||||
|
return Task.FromResult(new DummyClass { SampleInt = 10 });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<object> GetTaskOfDummyClassAsObject()
|
||||||
|
{
|
||||||
|
return Task.FromResult<object>(new DummyClass { SampleInt = 10 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue