Added ValueTask support to API Explorer response types. (#13739)

(cherry picked from commit 24b051de5ee386521f8b286c7c7d4f69ac1f2244)

Fixes https://github.com/aspnet/AspNetCore/issues/4883
This commit is contained in:
Travis Illig 2019-09-06 12:13:42 -07:00 committed by Pranav K
parent f9c15caa7a
commit f1f615282d
2 changed files with 69 additions and 3 deletions

View File

@ -214,7 +214,8 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
{
var declaredReturnType = action.MethodInfo.ReturnType;
if (declaredReturnType == typeof(void) ||
declaredReturnType == typeof(Task))
declaredReturnType == typeof(Task) ||
declaredReturnType == typeof(ValueTask))
{
return typeof(void);
}
@ -222,7 +223,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
// Unwrap the type if it's a Task<T>. The Task (non-generic) case was already handled.
var unwrappedType = declaredReturnType;
if (declaredReturnType.IsGenericType &&
declaredReturnType.GetGenericTypeDefinition() == typeof(Task<>))
(declaredReturnType.GetGenericTypeDefinition() == typeof(Task<>) || declaredReturnType.GetGenericTypeDefinition() == typeof(ValueTask<>)))
{
unwrappedType = declaredReturnType.GetGenericArguments()[0];
}

View File

@ -472,6 +472,22 @@ namespace Microsoft.AspNetCore.Mvc.Description
Assert.NotNull(responseType.ModelMetadata);
}
[Fact]
public void GetApiDescription_PopulatesResponseType_WithValueTaskOfProduct()
{
// Arrange
var action = CreateActionDescriptor(nameof(ReturnsValueTaskOfProduct));
// Act
var descriptions = GetApiDescriptions(action);
// Assert
var description = Assert.Single(descriptions);
var responseType = Assert.Single(description.SupportedResponseTypes);
Assert.Equal(typeof(Product), responseType.Type);
Assert.NotNull(responseType.ModelMetadata);
}
[Theory]
[InlineData(nameof(ReturnsObject))]
[InlineData(nameof(ReturnsActionResult))]
@ -479,6 +495,9 @@ namespace Microsoft.AspNetCore.Mvc.Description
[InlineData(nameof(ReturnsTaskOfObject))]
[InlineData(nameof(ReturnsTaskOfActionResult))]
[InlineData(nameof(ReturnsTaskOfJsonResult))]
[InlineData(nameof(ReturnsValueTaskOfObject))]
[InlineData(nameof(ReturnsValueTaskOfActionResult))]
[InlineData(nameof(ReturnsValueTaskOfJsonResult))]
public void GetApiDescription_DoesNotPopulatesResponseInformation_WhenUnknown(string methodName)
{
// Arrange
@ -521,7 +540,7 @@ namespace Microsoft.AspNetCore.Mvc.Description
},
{
typeof(DefaultApiDescriptionProviderTest),
nameof(DefaultApiDescriptionProviderTest.ReturnsActionResult),
nameof(DefaultApiDescriptionProviderTest.ReturnsValueTaskOfActionResult),
filterDescriptors
},
{
@ -624,6 +643,11 @@ namespace Microsoft.AspNetCore.Mvc.Description
nameof(DefaultApiDescriptionProviderTest.ReturnsTask),
filterDescriptors
},
{
typeof(DefaultApiDescriptionProviderTest),
nameof(DefaultApiDescriptionProviderTest.ReturnsValueTask),
filterDescriptors
},
{
typeof(DerivedProducesController),
nameof(DerivedProducesController.ReturnsVoid),
@ -634,6 +658,11 @@ namespace Microsoft.AspNetCore.Mvc.Description
nameof(DerivedProducesController.ReturnsTask),
filterDescriptors
},
{
typeof(DerivedProducesController),
nameof(DerivedProducesController.ReturnsValueTask),
filterDescriptors
},
};
}
}
@ -895,6 +924,7 @@ namespace Microsoft.AspNetCore.Mvc.Description
[Theory]
[InlineData(nameof(ReturnsVoid))]
[InlineData(nameof(ReturnsTask))]
[InlineData(nameof(ReturnsValueTask))]
public void GetApiDescription_DefaultVoidStatus(string methodName)
{
// Arrange
@ -914,6 +944,7 @@ namespace Microsoft.AspNetCore.Mvc.Description
[Theory]
[InlineData(nameof(ReturnsVoid))]
[InlineData(nameof(ReturnsTask))]
[InlineData(nameof(ReturnsValueTask))]
public void GetApiDescription_VoidWithResponseTypeAttributeStatus(string methodName)
{
// Arrange
@ -944,6 +975,10 @@ namespace Microsoft.AspNetCore.Mvc.Description
[InlineData(nameof(ReturnsTask))]
[InlineData(nameof(ReturnsTaskOfActionResult))]
[InlineData(nameof(ReturnsTaskOfJsonResult))]
[InlineData(nameof(ReturnsValueTask))]
[InlineData(nameof(ReturnsValueTaskOfObject))]
[InlineData(nameof(ReturnsValueTaskOfActionResult))]
[InlineData(nameof(ReturnsValueTaskOfJsonResult))]
public void GetApiDescription_PopulatesResponseInformation_WhenSetByFilter(string methodName)
{
// Arrange
@ -2026,6 +2061,31 @@ namespace Microsoft.AspNetCore.Mvc.Description
return null;
}
private ValueTask<Product> ReturnsValueTaskOfProduct()
{
return default;
}
private ValueTask<object> ReturnsValueTaskOfObject()
{
return default;
}
private ValueTask ReturnsValueTask()
{
return default;
}
private ValueTask<IActionResult> ReturnsValueTaskOfActionResult()
{
return default;
}
private ValueTask<JsonResult> ReturnsValueTaskOfJsonResult()
{
return default;
}
private Product ReturnsProduct()
{
return null;
@ -2196,6 +2256,11 @@ namespace Microsoft.AspNetCore.Mvc.Description
return null;
}
public ValueTask ReturnsValueTask()
{
return default;
}
public void ReturnsVoid()
{
}